Прочитать файл заблокированный другим процессом
Подскажите, как получить все хендлы процесса по 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;
}
}
}
}