Delphi - 获取应用程序打开了哪些文件

发布于 2024-08-07 10:36:22 字数 56 浏览 2 评论 0原文

如何使用 Delphi 获取应用程序打开的文件的列表? 例如 winword.exe 打开哪些文件

How can I get the list of opened files by an application, using Delphi?
For example what files are opened by winword.exe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

樱花落人离去 2024-08-14 10:36:22

使用本机 API 函数 NtQuerySystemInformation 您可以列出所有进程的所有打开句柄。

试试这个例子

program ListAllHandles;

{$APPTYPE CONSOLE}

uses
  PSApi,
  Windows,
  SysUtils;

const
SystemHandleInformation       = $10;
STATUS_SUCCESS               = $00000000;
STATUS_BUFFER_OVERFLOW        = $80000005;
STATUS_INFO_LENGTH_MISMATCH   = $C0000004;
DefaulBUFFERSIZE              = $100000;


type
 OBJECT_INFORMATION_CLASS = (ObjectBasicInformation,ObjectNameInformation,ObjectTypeInformation,ObjectAllTypesInformation,ObjectHandleInformation );

 SYSTEM_HANDLE=packed record
 uIdProcess:ULONG;
 ObjectType:UCHAR;
 Flags     :UCHAR;
 Handle    :Word;
 pObject   :Pointer;
 GrantedAccess:ACCESS_MASK;
 end;

 PSYSTEM_HANDLE      = ^SYSTEM_HANDLE;
 SYSTEM_HANDLE_ARRAY = Array[0..0] of SYSTEM_HANDLE;
 PSYSTEM_HANDLE_ARRAY= ^SYSTEM_HANDLE_ARRAY;

  SYSTEM_HANDLE_INFORMATION=packed record
 uCount:ULONG;
 Handles:SYSTEM_HANDLE_ARRAY;
 end;
 PSYSTEM_HANDLE_INFORMATION=^SYSTEM_HANDLE_INFORMATION;

 TNtQuerySystemInformation=function (SystemInformationClass:DWORD; SystemInformation:pointer; SystemInformationLength:DWORD;  ReturnLength:PDWORD):THandle; stdcall;
 TNtQueryObject           =function (ObjectHandle:cardinal; ObjectInformationClass:OBJECT_INFORMATION_CLASS; ObjectInformation:pointer; Length:ULONG;ResultLength:PDWORD):THandle;stdcall;

 UNICODE_STRING=packed record
    Length       :Word;
    MaximumLength:Word;
    Buffer       :PWideChar;
 end;

 OBJECT_NAME_INFORMATION=UNICODE_STRING;
 POBJECT_NAME_INFORMATION=^OBJECT_NAME_INFORMATION;

Var
 NTQueryObject           :TNtQueryObject;
 NTQuerySystemInformation:TNTQuerySystemInformation;


function GetObjectInfo(hObject:cardinal; objInfoClass:OBJECT_INFORMATION_CLASS):LPWSTR;
var
 pObjectInfo:POBJECT_NAME_INFORMATION;
 HDummy     :THandle;
 dwSize     :DWORD;
begin
  Result:=nil;
  dwSize      := sizeof(OBJECT_NAME_INFORMATION);
  pObjectInfo := AllocMem(dwSize);
  HDummy      := NTQueryObject(hObject, objInfoClass, pObjectInfo,dwSize, @dwSize);

  if((HDummy = STATUS_BUFFER_OVERFLOW) or (HDummy = STATUS_INFO_LENGTH_MISMATCH)) then
    begin
   FreeMem(pObjectInfo);
   pObjectInfo := AllocMem(dwSize);
   HDummy      := NTQueryObject(hObject, objInfoClass, pObjectInfo,dwSize, @dwSize);
  end;

  if((HDummy >= STATUS_SUCCESS) and (pObjectInfo.Buffer <> nil)) then
  begin
   Result := AllocMem(pObjectInfo.Length + sizeof(WCHAR));
   CopyMemory(result, pObjectInfo.Buffer, pObjectInfo.Length);
  end;
  FreeMem(pObjectInfo);
end;

Procedure EnumerateOpenFiles();
var
 sDummy      : string;
 hProcess    : THandle;
 hObject     : THandle;
 ResultLength: DWORD;
 aBufferSize : DWORD;
 aIndex      : Integer;
 pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
 HDummy      : THandle;
 lpwsName    : PWideChar;
 lpwsType    : PWideChar;
 lpszProcess : PAnsiChar;
begin
    AbufferSize      := DefaulBUFFERSIZE;
  pHandleInfo      := AllocMem(AbufferSize);
  HDummy           := NTQuerySystemInformation(DWORD(SystemHandleInformation), pHandleInfo,AbufferSize, @ResultLength);  //Get the list of handles

  if(HDummy = STATUS_SUCCESS) then  //If no error continue
    begin

      for aIndex:=0 to pHandleInfo^.uCount-1 do   //iterate the list
      begin
    hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pHandleInfo.Handles[aIndex].uIdProcess);  //open the process to get aditional info
    if(hProcess <> INVALID_HANDLE_VALUE) then  //Check valid handle
        begin
     hObject := 0;
     if DuplicateHandle(hProcess, pHandleInfo.Handles[aIndex].Handle,GetCurrentProcess(), @hObject, STANDARD_RIGHTS_REQUIRED,FALSE, 0) then  //Get  a copy of the original handle
          begin
      lpwsName := GetObjectInfo(hObject, ObjectNameInformation); //Get the filename linked to the handle
      if (lpwsName <> nil)  then
            begin
       lpwsType    := GetObjectInfo(hObject, ObjectTypeInformation);
       lpszProcess := AllocMem(MAX_PATH);

       if GetModuleFileNameEx(hProcess, 0,lpszProcess, MAX_PATH)<>0 then  //get the name of the process
               sDummy:=ExtractFileName(lpszProcess)
              else
               sDummy:= 'System Process';

              Writeln('PID      ',pHandleInfo.Handles[aIndex].uIdProcess);
              Writeln('Handle   ',pHandleInfo.Handles[aIndex].Handle);
              Writeln('Process  ',sDummy);
              Writeln('FileName ',string(lpwsName));
              Writeln;

              FreeMem(lpwsName);
              FreeMem(lpwsType);
              FreeMem(lpszProcess);
      end;
      CloseHandle(hObject);
     end;
     CloseHandle(hProcess);
    end;
   end;
  end;
  FreeMem(pHandleInfo);

end;

begin
  try
    NTQueryObject            := GetProcAddress(GetModuleHandle('NTDLL.DLL'), 'NtQueryObject');
    NTQuerySystemInformation := GetProcAddress(GetModuleHandle('NTDLL.DLL'), 'NtQuerySystemInformation');
   if (@NTQuerySystemInformation<>nil) and (@NTQuerySystemInformation<>nil) then
    EnumerateOpenFiles();
    Readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

Using the Native API function NtQuerySystemInformation you can list all open handles from all processes.

try this example

program ListAllHandles;

{$APPTYPE CONSOLE}

uses
  PSApi,
  Windows,
  SysUtils;

const
SystemHandleInformation       = $10;
STATUS_SUCCESS               = $00000000;
STATUS_BUFFER_OVERFLOW        = $80000005;
STATUS_INFO_LENGTH_MISMATCH   = $C0000004;
DefaulBUFFERSIZE              = $100000;


type
 OBJECT_INFORMATION_CLASS = (ObjectBasicInformation,ObjectNameInformation,ObjectTypeInformation,ObjectAllTypesInformation,ObjectHandleInformation );

 SYSTEM_HANDLE=packed record
 uIdProcess:ULONG;
 ObjectType:UCHAR;
 Flags     :UCHAR;
 Handle    :Word;
 pObject   :Pointer;
 GrantedAccess:ACCESS_MASK;
 end;

 PSYSTEM_HANDLE      = ^SYSTEM_HANDLE;
 SYSTEM_HANDLE_ARRAY = Array[0..0] of SYSTEM_HANDLE;
 PSYSTEM_HANDLE_ARRAY= ^SYSTEM_HANDLE_ARRAY;

  SYSTEM_HANDLE_INFORMATION=packed record
 uCount:ULONG;
 Handles:SYSTEM_HANDLE_ARRAY;
 end;
 PSYSTEM_HANDLE_INFORMATION=^SYSTEM_HANDLE_INFORMATION;

 TNtQuerySystemInformation=function (SystemInformationClass:DWORD; SystemInformation:pointer; SystemInformationLength:DWORD;  ReturnLength:PDWORD):THandle; stdcall;
 TNtQueryObject           =function (ObjectHandle:cardinal; ObjectInformationClass:OBJECT_INFORMATION_CLASS; ObjectInformation:pointer; Length:ULONG;ResultLength:PDWORD):THandle;stdcall;

 UNICODE_STRING=packed record
    Length       :Word;
    MaximumLength:Word;
    Buffer       :PWideChar;
 end;

 OBJECT_NAME_INFORMATION=UNICODE_STRING;
 POBJECT_NAME_INFORMATION=^OBJECT_NAME_INFORMATION;

Var
 NTQueryObject           :TNtQueryObject;
 NTQuerySystemInformation:TNTQuerySystemInformation;


function GetObjectInfo(hObject:cardinal; objInfoClass:OBJECT_INFORMATION_CLASS):LPWSTR;
var
 pObjectInfo:POBJECT_NAME_INFORMATION;
 HDummy     :THandle;
 dwSize     :DWORD;
begin
  Result:=nil;
  dwSize      := sizeof(OBJECT_NAME_INFORMATION);
  pObjectInfo := AllocMem(dwSize);
  HDummy      := NTQueryObject(hObject, objInfoClass, pObjectInfo,dwSize, @dwSize);

  if((HDummy = STATUS_BUFFER_OVERFLOW) or (HDummy = STATUS_INFO_LENGTH_MISMATCH)) then
    begin
   FreeMem(pObjectInfo);
   pObjectInfo := AllocMem(dwSize);
   HDummy      := NTQueryObject(hObject, objInfoClass, pObjectInfo,dwSize, @dwSize);
  end;

  if((HDummy >= STATUS_SUCCESS) and (pObjectInfo.Buffer <> nil)) then
  begin
   Result := AllocMem(pObjectInfo.Length + sizeof(WCHAR));
   CopyMemory(result, pObjectInfo.Buffer, pObjectInfo.Length);
  end;
  FreeMem(pObjectInfo);
end;

Procedure EnumerateOpenFiles();
var
 sDummy      : string;
 hProcess    : THandle;
 hObject     : THandle;
 ResultLength: DWORD;
 aBufferSize : DWORD;
 aIndex      : Integer;
 pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
 HDummy      : THandle;
 lpwsName    : PWideChar;
 lpwsType    : PWideChar;
 lpszProcess : PAnsiChar;
begin
    AbufferSize      := DefaulBUFFERSIZE;
  pHandleInfo      := AllocMem(AbufferSize);
  HDummy           := NTQuerySystemInformation(DWORD(SystemHandleInformation), pHandleInfo,AbufferSize, @ResultLength);  //Get the list of handles

  if(HDummy = STATUS_SUCCESS) then  //If no error continue
    begin

      for aIndex:=0 to pHandleInfo^.uCount-1 do   //iterate the list
      begin
    hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pHandleInfo.Handles[aIndex].uIdProcess);  //open the process to get aditional info
    if(hProcess <> INVALID_HANDLE_VALUE) then  //Check valid handle
        begin
     hObject := 0;
     if DuplicateHandle(hProcess, pHandleInfo.Handles[aIndex].Handle,GetCurrentProcess(), @hObject, STANDARD_RIGHTS_REQUIRED,FALSE, 0) then  //Get  a copy of the original handle
          begin
      lpwsName := GetObjectInfo(hObject, ObjectNameInformation); //Get the filename linked to the handle
      if (lpwsName <> nil)  then
            begin
       lpwsType    := GetObjectInfo(hObject, ObjectTypeInformation);
       lpszProcess := AllocMem(MAX_PATH);

       if GetModuleFileNameEx(hProcess, 0,lpszProcess, MAX_PATH)<>0 then  //get the name of the process
               sDummy:=ExtractFileName(lpszProcess)
              else
               sDummy:= 'System Process';

              Writeln('PID      ',pHandleInfo.Handles[aIndex].uIdProcess);
              Writeln('Handle   ',pHandleInfo.Handles[aIndex].Handle);
              Writeln('Process  ',sDummy);
              Writeln('FileName ',string(lpwsName));
              Writeln;

              FreeMem(lpwsName);
              FreeMem(lpwsType);
              FreeMem(lpszProcess);
      end;
      CloseHandle(hObject);
     end;
     CloseHandle(hProcess);
    end;
   end;
  end;
  FreeMem(pHandleInfo);

end;

begin
  try
    NTQueryObject            := GetProcAddress(GetModuleHandle('NTDLL.DLL'), 'NtQueryObject');
    NTQuerySystemInformation := GetProcAddress(GetModuleHandle('NTDLL.DLL'), 'NtQuerySystemInformation');
   if (@NTQuerySystemInformation<>nil) and (@NTQuerySystemInformation<>nil) then
    EnumerateOpenFiles();
    Readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
小嗷兮 2024-08-14 10:36:22

您可以移植 walkobjects.cpp 或运行 为您执行此操作的命令行进程并解析其输出。

You could port walkobjects.cpp or run a command line process that does it for you and parse it's output.

能否归途做我良人 2024-08-14 10:36:22

我查看了 MSDN 页面...
它说 NtQuerySystemInformation() 是操作系统内部过程,
并且我们不建议使用它:

NtQuerySystemInformation 函数
它返回的结构是
操作系统内部和
可能会因某个版本而发生变化
窗户到另一个。为了维持
您的应用程序的兼容性,它
最好使用替代方案
前面提到的功能
相反。

I've looked at the MSDN page...
it said NtQuerySystemInformation() is an OS internal proc,
and that we're not recommended to use it:

The NtQuerySystemInformation function
and the structures that it returns are
internal to the operating system and
subject to change from one release of
Windows to another. To maintain the
compatibility of your application, it
is better to use the alternate
functions previously mentioned
instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文