提问人:Michael Marcel 提问时间:8/8/2023 最后编辑:marc_sMichael Marcel 更新时间:8/21/2023 访问量:176
获取使用文件的 ProcessId
Get ProcessId that is using a file
问:
重要提示:我们使用 DELPHI 7。
我有一个问题来获取正在使用的文件。ProcessId
只是为了让您知道,在我们的软件中,我们需要向用户显示哪个进程正在使用我们需要的文件。
为此,我曾经获取过“进程”列表和“句柄”列表。NtQuerySystemInformation
之后,我使用了那些带有文件句柄的进程 ID (ObjectType = 28)OpenProcess
然后我曾经得到文件句柄。DuplicateHandle
让我们看看代码:
function GetProcessIdUsingFile(const TargetFileName:string): DWORD;
var
hProcess : THandle;
hFile : THandle;
SystemInformationLength : DWORD;
Index : Integer;
pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
hQuery : THandle;
FileName : String;
ReturnInformation : LongBool;
FileInfo : _BY_HANDLE_FILE_INFORMATION;
//Novo
cbRet : DWORD;
cbSize : DWORD;
begin
Result:= 0;
cbSize := $5000;
GetMem(pHandleInfo, cbSize);
repeat
cbSize := cbSize * 2;
ReallocMem(pHandleInfo, cbSize);
hQuery := NtQuerySystemInformation(SystemHandleInformation, pHandleInfo, cbSize, @cbRet);
until hQuery <> STATUS_INFO_LENGTH_MISMATCH;
try
if(hQuery = STATUS_SUCCESS) then
begin
for Index:=0 to pHandleInfo^.uCount-1 do
if pHandleInfo^.Handles[Index].ObjectType=28 then
begin
hProcess := OpenProcess(PROCESS_DUP_HANDLE, FALSE, pHandleInfo^.Handles[Index].uIdProcess);
if(hProcess <> INVALID_HANDLE_VALUE) then
begin
try
if not DuplicateHandle(hProcess, pHandleInfo^.Handles[Index].Handle,GetCurrentProcess(), @hFile, 0 ,FALSE, DUPLICATE_SAME_ACCESS) then
hFile := INVALID_HANDLE_VALUE;
if (hFile<>INVALID_HANDLE_VALUE) then
begin
try
FileName := GetFileNameByHandle(hFile);
finally
CloseHandle(hFile);
end;
end
else
FileName := '';
finally
CloseHandle(hProcess);
end;
if CompareText(ExtractFileName(FileName), TargetFileName)=0 then
Result := pHandleInfo^.Handles[Index].uIdProcess;
end;
end;
end;
finally
if pHandleInfo<>nil then
FreeMem(pHandleInfo);
end;
end;
所以,我创造了GetFileNameByHandle
此函数从前面的代码中接收文件句柄,并尝试使用 和 获取其文件名。NtQueryInformationFile
NtQueryObject
但是,每一次回电.如何获取其文件名?NtQueryInformationFile
STATUS_OBJECT_TYPE_MISMATCH
让我向你展示这个函数的代码:
function GetFileNameByHandle(hFile: THandle): String;
var
dwReturn: DWORD;
FileNameInfoRecord: FILE_NAME_INFORMATION;
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
IoStatusBlock: IO_STATUS_BLOCK;
ntSTATUS : DWORD;
FileName : array [0..MAX_PATH - 1] of WCHAR;
begin
FillChar(FileName, SizeOf(FileName), 0);
FillChar(FileNameInfoRecord.FileName, SizeOf(FileNameInfoRecord.FileName), 0);
FileNameInfoRecord.FileNameLength := 0;
ntSTATUS := NtQueryInformationFile(hFile, @IoStatusBlock, @FileNameInfoRecord, SizeOf(FILE_NAME_INFORMATION) * 2 + 1, FileNameInformation);
if ntSTATUS = STATUS_SUCCESS then
begin
// NEVER ENTER HERE... WHY?
ntSTATUS := NtQueryObject(hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
if ntSTATUS = STATUS_SUCCESS then
begin
WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @FileName[0], MAX_PATH, nil, nil);
end
else
begin
ntSTATUS := STATUS_SUCCESS;
WideCharToMultiByte(CP_ACP, 0, @FileNameInfoRecord.FileName[1], IoStatusBlock.Information, @FileName[0], MAX_PATH, nil, nil);
end;
end;
Result := WideCharToString(@FileName);
end;
之后,我比较函数中的文件名以返回 PID。GetProcessIdUsingFile
我使用此代码作为基础,并尝试了一些修改,但没有任何效果:
如果你们需要更多信息,请LMK。
答: 暂无答案
评论
GetFileInformationByHandleEx()
而不是 +。NtQueryInformationFile
NtQueryObject
GetFileInformationByHandleEx
NtQueryInformationFile
GetFileInformationByHandleEx
FILE_NAME_INFORMATION
SizeOf(FILE_NAME_INFORMATION)
NtQueryInformationFile
FILE_NAME_INFORMATION
SizeOf(FILE_NAME_INFORMATION) * 2 + 1