C#通过句柄获取路径/文件名(hWnd)32和64位

时间:2011-01-22 15:27:48

标签: c# .net path 64-bit filenames

我得到以下代码来通过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

4 个答案:

答案 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位运行。这是一个理想的情况,假设:

  1. 您已正确编写了P / Invoke定义(即,在适当情况下使用IntPtr,而不是Integer)。
  2. 您不依赖于编译为32位的第三方DLL(您没有源代码)。

答案 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; }
    }