【问题标题】:Delphi - get what files are opened by an applicationDelphi - 获取应用程序打开了哪些文件
【发布时间】:2010-12-07 05:06:06
【问题描述】:

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

【问题讨论】:

    标签: delphi winapi file process


    【解决方案1】:

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

    NtQuerySystemInformation 函数 它返回的结构是 操作系统内部和 可能会从一个版本的更改 窗户到另一个。为了维持 您的应用程序的兼容性,它 最好使用备用 前面提到的功能 而是。

    【讨论】:

      【解决方案2】:

      使用 Native 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.
      

      【讨论】:

      • Native API 的头文件存在于 Jedi ApiLib (JwaNative) (Jwa) 以及 Windows SDK 的其余部分中,这样您就不必像上面那样自己声明它们。如果您对 Jedi ApiLib 不熟悉,我们的博客可能是一个很好的起点 (blog.delphi-jedi.net)
      • 嗨@Remko,我知道Jedi APILib,这只是NtQuerySystemInformation API 的一个简单示例,没有依赖关系。 ;)
      • 嗨 RRUZ。当我运行您的代码时,我得到文件名行:“FileName \BaseNamedObjects\CTF.Compart.MutexDefaultS-1-5-21-2000478354-606747145-1801674531-500”。我错过了什么吗?我做错了什么?
      • NtQuerySystemInformation API 检索系统中的所有句柄。这包括文件句柄、互斥体句柄、事件句柄。您必须检查 pHandleInfo.Handles[aIndex].ObjectType 字段以确定句柄的类型。
      • @RRUZ,此代码无效。请问可以修吗? NTQuerySystemInformation() 没有列出任何进程。
      【解决方案3】:

      您可以移植walkobjects.cpp 或运行command line process that does it for you 并解析它的输出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-23
        • 1970-01-01
        • 2011-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多