I got the following code to get path/filename by 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();
}
it works perfect in 32 bit but I get error in 64bit > "Only part of the ReadProcessMemory or WriteProcessMemory request was completed." the project is compiled as x86 (platform target x86).
How can I fix it?
~Thanks Ron
It appears from your question that you've currently compiled your program as a 32-bit application. However, the process you're trying to query (assuming you're running on a 64-bit version of Windows) is undoubtedly a 64-bit one. That kind of thing isn't allowed. Although you can run 32-bit applications on 64-bit versions of Windows, they run under the dedicated Windows on Windows (WOW64) subsystem. That's why you're getting a
Win32Exception
claiming that "Only part of a ReadProcessMemory or WriteProcessMemory request was completed". I agree it's not the most descriptive of error messages if you don't already know how Windows manages 32-bit and 64-bit processes, but armed with this knowledge it makes at least a little more sense.The solution is to compile your application as a 64-bit application (x64), or for "Any CPU". Everything should work as expected after that. If possible, I suggest using "Any CPU", which will allow the application to run in 32-bit mode on 32-bit OSes and 64-bit on 64-bit OSes. Which is really the ideal set of circumstances, assuming that:
IntPtr
where appropriate, instead ofInteger
).This thing is absolutely possible from a 32 bit application when checking a 64 bit process, though not as straightforward as it would be if it were a 64 bit compiled application:
I'm not aware of a known problem with this, it smells environmental. The error is very low level, probably the wow64 emulation layer. I can only suggest you punt and use a different way to get the same info. You can use WMI, Win32_Process class. Run a select query on ProcessId, the ExecutablePath property gives you what you are looking for. Use the WMI Code Creator utility to experiment, it auto-generates the C# code you need. The odds are however not zero that this will fail the same way.
It works well for me on a 64x machine. The only changes to the code are checking the values, as: