为什么我在64位Windows 8上从GetModuleFileNameEx中得到废话?

时间:2014-07-31 15:51:55

标签: delphi winapi 32bit-64bit

我有这个

function NazwaProcesu(const uchwyt: Thandle): string;
var
  pid: DWORD;
  hProcess: Thandle;
  sciezka: array [0..MAX_PATH - 1] of char;
begin
  GetWindowThreadProcessId(uchwyt, pid);
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pid);
  if hProcess <> 0 then
    try
      GetModuleFileNameEx(hProcess, 0, sciezka, MAX_PATH)
    finally
      Result := sciezka;
      CloseHandle(hProcess);
    end;
end;

在Windows 7上32位没问题。在Win 8 x64上我有这个:

enter image description here

我认为最后3个条目应该是explorer.exe。谢谢你的帮助。

3 个答案:

答案 0 :(得分:11)

据我所知,当在32位进程中执行代码时,此方法将无法检索64位进程信息。在WOW64模拟器中运行时,这种问题很常见,避免此类问题的最简单方法是在WOW64模拟器外部运行代码。也就是说,以64位进程运行代码。

解决此问题的其他可能方法,如果您无法重新编译为64位:

  1. 使用单独的64位进程和一些IPC来检索信息。
  2. 使用WMI获取模块文件名。
  3. 使用QueryFullProcessImageName
  4. 我总是强调的另一点是错误检查很重要。致电GetModuleFileNameEx时,您无法检查错误。调用显然是失败的,这就是为什么你最终得到一个未初始化的文本缓冲区。始终检查Windows API调用是否有错误。

答案 1 :(得分:3)

修改后:

function NazwaProcesu(const uchwyt: Thandle): string;
type
  TQueryFullProcessImageName = function(hProcess: Thandle; dwFlags: DWORD; lpExeName: PChar; nSize: PDWORD): BOOL; stdcall;
var
  pid: DWORD;
  hProcess: Thandle;
  sciezka: array [0 .. MAX_PATH - 1] of Char;
  QueryFullProcessImageName: TQueryFullProcessImageName;
  nSize: cardinal;
begin
  Result := '';
  GetWindowThreadProcessId(uchwyt, pid);
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, pid);
  if hProcess <> 0 then
    try
      if GetModuleFileNameEX(hProcess, 0, sciezka, MAX_PATH) <> 0 then Result := sciezka
      else if Win32MajorVersion >= 6 then
      begin
        nSize := MAX_PATH;
        ZeroMemory(@sciezka, MAX_PATH);
        @QueryFullProcessImageName := GetProcAddress(GetModuleHandle('kernel32'), 'QueryFullProcessImageNameW');
        if Assigned(QueryFullProcessImageName) then
          if QueryFullProcessImageName(hProcess, 0, sciezka, @nSize) then Result := sciezka
      end;
    finally
      CloseHandle(hProcess);
    end;
end;

enter image description here

答案 2 :(得分:0)

我最终寻求了一个完全不同的解决方法。关于PE标头的This answer提到了32位和64位Windows可执行文件中的PE标头。您可以完全绕开WinAPI检查,并通过在Binary模式下读取目标可执行文件并检查其是否与PE签名相匹配来检查目标可执行文件。

遗憾的是,在线上没有太多有关此问题的信息。我记得在某个论坛上看到过这个问题,该论坛被明确列为bug,但这大约是10年前。我希望当我们讨论这个问题时,更多的人意识到它。

相关问题