如何从32位进程中获取给定PID的64位进程的可执行路径



我正在开发一个32位的C++Windows应用程序,由于我无法控制的原因,它需要保持32位。该应用程序需要能够获得给定PID的其他运行进程的可执行文件的完整路径。

通常,对于64位应用程序,您可以使用OpenProcess()获取具有特定PID的进程的句柄,然后将其返回的句柄传递给GetModuleFileNameEx()以获取其可执行路径。然而,如果你试图从32位进程中获取64位进程的句柄,OpenProcess()将失败,因此我无法使用此方法

有办法做到这一点吗?

注释中已经提到了一些方法。最好和最简单的方法可能是用PROCESS_QUERY_LIMITED_INFORMATION打开流程,并在上面调用QueryFullProcessImageName,正如雷米·勒博和RbMm所写的那样。

不过,让我展示另一种方式:您可以利用WMI。请注意,这不是迄今为止最好的选择(因为它在幕后非常"昂贵"(,但如果你因为某种原因无法使用其他选项,尽管如此,了解一下可能会有所帮助。

WMI类Win32_Process有一个字段ExecutablePath,其中包含您要查找的信息。您也应该能够从32位进程中读取它。

以下是如何使用C++从WMI读取数据的说明。

PowerShell中的示例:

PS Z:> Get-WmiObject -Query 'Select ExecutablePath From Win32_Process Where ProcessId = 6056'

__GENUS          : 2
__CLASS          : Win32_Process
__SUPERCLASS     :
__DYNASTY        :
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ExecutablePath   : C:Program Files (x86)Moo0AlwaysOnTop 1.24WindowMenuPlus64.exe
PSComputerName   :

我遇到这个问题是想从powershell中找到一种方法。Get-WmiObject方法的失败方式与(Get-Process(.Path相同,即虽然可以检索进程列表(及其PID和进程名称(,但当进程的位与shell不匹配时,无法检索模块信息(包括路径(。

对这个问题的评论帮助了我,尤其是@RemyLebeau,我提出了以下建议。我知道这个问题最初是c++,但也许这会对某人有所帮助。它是相同的WinAPI调用,加载到powershell中的内联c范围中。

$pinvoke = Add-Type -PassThru -Name pinvoke -MemberDefinition @'
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool CloseHandle(
IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr OpenProcess(
uint processAccess,
bool bInheritHandle,
int processId);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool QueryFullProcessImageName(
IntPtr hProcess,
int dwFlags,
System.Text.StringBuilder lpExeName,
ref int lpdwSize);
private const int QueryLimitedInformation = 0x00001000;
public static string GetProcessPath(int pid)
{
var size = 1024;
var sb = new System.Text.StringBuilder(size);
var handle = OpenProcess(QueryLimitedInformation, false, pid);
if (handle == IntPtr.Zero) return null;
var success = QueryFullProcessImageName(handle, 0, sb, ref size);
CloseHandle(handle);
if (!success) return null;
return sb.ToString();
}
'@

然后你可以通过获得32或64位进程的路径

$pinvoke::GetProcessPath($pid)

最新更新