Прочитать файл заблокированный другим процессом

Подскажите, как получить все хендлы процесса по ID, получить дубликат хендла, и напрямую уже читать залоченный файл.


Я попробовал следующее:

namespace ReadLockFile
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    public class HandleHelper
    {
        [DllImport("kernel32.dll")]
        private static extern int OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CloseHandle(int hObject);

        [DllImport("ntdll.dll")]
        private static extern int NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, out int ReturnLength);

        [StructLayout(LayoutKind.Sequential)]
        public struct SYSTEM_HANDLE_INFORMATION
        {
            public int ProcessId;
            public byte ObjectTypeNumber;
            public byte Flags;
            public ushort Handle;
            public int Object;
            public uint GrantedAccess;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct UNICODE_STRING
        {
            public ushort Length;
            public ushort MaximumLength;
            public IntPtr Buffer;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct OBJECT_NAME_INFORMATION
        {
            public UNICODE_STRING Name;
        }

        [DllImport("ntdll.dll")]
        private static extern int NtQueryObject(IntPtr ObjectHandle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength, out int ReturnLength);

        private const int SystemHandleInformation = 16;
        private const int ObjectNameInformation = 1;
        private const int STATUS_INFO_LENGTH_MISMATCH = unchecked((int)0xc0000004);

        public static Dictionary<int, string> GetHandleNames(int processId)
        {
            Dictionary<int, string> handleNames = new Dictionary<int, string>();

            try
            {
                IntPtr handleInformation;
                int handleInformationLength = 0x10000;
                int returnLength;

                handleInformation = Marshal.AllocHGlobal(handleInformationLength);

                NtQuerySystemInformation(SystemHandleInformation, handleInformation, handleInformationLength, out returnLength);

                int handleCount = Marshal.ReadInt32(handleInformation);

                IntPtr handleTable = IntPtr.Add(handleInformation, 4);

                SYSTEM_HANDLE_INFORMATION[] handles = new SYSTEM_HANDLE_INFORMATION[handleCount];

                for (int i = 0; i < handleCount; i++)
                {
                    handles[i] = (SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(handleTable, typeof(SYSTEM_HANDLE_INFORMATION));

                    if (handles[i].ProcessId == processId)
                    {
                        IntPtr handleObject = IntPtr.Zero;
                        int length = 0x100;
                        IntPtr objectNameInformation = Marshal.AllocHGlobal(length);

                        int status;

                        while ((status = NtQueryObject(handleObject, ObjectNameInformation, objectNameInformation, length, out returnLength)) == STATUS_INFO_LENGTH_MISMATCH)
                        {
                            length = returnLength;
                            Marshal.FreeHGlobal(objectNameInformation);
                            objectNameInformation = Marshal.AllocHGlobal(length);
                        }

                        if (status >= 0)
                        {
                            UNICODE_STRING objectName = (UNICODE_STRING)Marshal.PtrToStructure(objectNameInformation, typeof(UNICODE_STRING));
                            string name = Marshal.PtrToStringUni(objectName.Buffer);

                            handleNames.Add(handles[i].Handle, name);
                        }

                        Marshal.FreeHGlobal(objectNameInformation);
                    }

                    handleTable = IntPtr.Add(handleTable, Marshal.SizeOf(typeof(SYSTEM_HANDLE_INFORMATION)));
                }

                Marshal.FreeHGlobal(handleInformation);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Произошла ошибка при получении хендлов: " + ex.Message);
            }

            return handleNames;
        }
    }
}

И вызывал

namespace ReadLockFile
{
    using System;
    using System.Collections.Generic;

    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Введите идентификатор процесса:");

            int processId = Convert.ToInt32(Console.ReadLine());

            Dictionary<int, string> handleNames = HandleHelper.GetHandleNames(processId);

            Console.WriteLine("Хендлы процесса:");

            foreach (KeyValuePair<int, string> handleName in handleNames)
            {
                Console.WriteLine("Хендл: {0}, Имя: {1}", handleName.Key, handleName.Value);
            }
            Console.Read();
        }


        // other 


        [Flags]
        public enum FileMapProtection : uint
        {
            PageReadonly = 2u,
            PageReadWrite = 4u,
            PageWriteCopy = 8u,
            PageExecuteRead = 0x20u,
            PageExecuteReadWrite = 0x40u,
            SectionCommit = 0x8000000u,
            SectionImage = 0x1000000u,
            SectionNoCache = 0x10000000u,
            SectionReserve = 0x4000000u
        }

        [Flags]
        public enum FileMapAccess : uint
        {
            FileMapCopy = 1u,
            FileMapWrite = 2u,
            FileMapRead = 4u,
            FileMapAllAccess = 0x1Fu,
            FileMapExecute = 0x20u
        }

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x1F0FFFu,
            Terminate = 1u,
            CreateThread = 2u,
            VirtualMemoryOperation = 8u,
            VirtualMemoryRead = 0x10u,
            VirtualMemoryWrite = 0x20u,
            DuplicateHandle = 0x40u,
            CreateProcess = 0x80u,
            SetQuota = 0x100u,
            SetInformation = 0x200u,
            QueryInformation = 0x400u,
            QueryLimitedInformation = 0x1000u,
            Synchronize = 0x100000u
        }

        [Flags]
        public enum DuplicateOptions
        {
            DUPLICATE_CLOSE_SOURCE = 1,
            DUPLICATE_SAME_ACCESS = 2
        }

        public struct ProcessFileHandle
        {
            public string ProcessName;
            public int ProcessID;
            public string FileName;
            public int FileHandleID;

            public ProcessFileHandle(string processName, int processID, string fileName, int fileHandleID)
            {
                ProcessName = processName;
                ProcessID = processID;
                FileName = fileName;
                FileHandleID = fileHandleID;
            }
        }
    }
}

Ответы (0 шт):