我得到以下代码来通过handle获取路径/文件名:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr handle, out uint processId);
public static string GetProcessPath(IntPtr hwnd)
{
uint pid = 0;
GetWindowThreadProcessId(hwnd, out pid);
Process proc = Process.GetProcessById((int)pid);
return proc.MainModule.FileName.ToString();
}
它在32位工作完美,但我在64位>中得到错误“只完成了ReadProcessMemory或WriteProcessMemory请求的一部分。” 该项目编译为x86(平台目标x86)。
我该如何解决?
〜谢谢Ron
答案 0 :(得分:2)
从您的问题看来,您当前已将程序编译为32位应用程序。但是,您尝试查询的过程(假设您在64位版本的Windows上运行)无疑是64位版本。 That kind of thing isn't allowed。虽然您可以在64位版本的Windows上运行32位应用程序,但它们可以在专用的Windows on Windows(WOW64)子系统下运行。这就是为什么你得到Win32Exception
声称“只完成了ReadProcessMemory或WriteProcessMemory请求的一部分”的原因。我同意,如果您还不知道Windows如何管理32位和64位进程,那么它不是最具描述性的错误消息,但是凭借这些知识,它至少会更有意义。
解决方案是将您的应用程序编译为64位应用程序(x64)或“任何CPU”。之后应该按预期工作。如果可能,我建议使用“Any CPU”,这将允许应用程序在32位操作系统上以32位模式运行,在64位操作系统上以64位运行。这是一个理想的情况,假设:
IntPtr
,而不是Integer
)。答案 1 :(得分:1)
我不知道这个已知的问题,它闻起来很环保。错误级别非常低,可能是wow64仿真层。我只能建议你平底船,并使用不同的方式来获得相同的信息。您可以使用WMI Win32_Process class。在ProcessId上运行select查询,ExecutablePath属性为您提供所需的内容。使用W MI Code Creator utility进行试验,它会自动生成您需要的C#代码。然而,赔率不是零,这将以同样的方式失败。
答案 2 :(得分:1)
在64x机器上适用于我。对代码的唯一更改是检查值,如:
if (hwnd != IntPtr.Zero)
{
if (pid != 0)
{
var p = Process.GetProcessById((int) pid)
if (p != null)
{
//...
}
}
}
答案 3 :(得分:0)
在检查64位进程时,32位应用程序绝对可以做到这一点,尽管不像它是64位编译应用程序那样简单:
[Flags]
enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000,
ReadControl = 0x00020000,
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
}
[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
private static extern bool QueryFullProcessImageName(IntPtr hprocess, int dwFlags, StringBuilder lpExeName, out int size);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hHandle);
private static Process GetProcessByHandle(IntPtr hwnd)
{
try
{
uint processID;
GetWindowThreadProcessId(hwnd, out processID);
return Process.GetProcessById((int)processID);
}
catch { return null; }
}
private static string GetExecutablePathAboveVista(int ProcessId)
{
var buffer = new StringBuilder(1024);
IntPtr hprocess = OpenProcess(ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION,
false, ProcessId);
if (hprocess != IntPtr.Zero)
{
try
{
int size = buffer.Capacity;
if (QueryFullProcessImageName(hprocess, 0, buffer, out size))
{
return buffer.ToString();
}
}
finally
{
CloseHandle(hprocess);
}
}
return null;
}
private static string GetWindowPath(IntPtr hwind)
{
try
{
Process currentProcess = GetProcessByHandle(hwind);
if (Environment.OSVersion.Version.Major >= 6)
{
string newMethReturn = GetExecutablePathAboveVista(currentProcess.Id);
if (!string.IsNullOrWhiteSpace(newMethReturn))
return newMethReturn;
}
if (currentProcess != null)
return currentProcess.MainModule.FileName;
else
return null;
}
catch
{ return null; }
}