2011-01-22 40 views
4

我得到了下面的代碼通過手柄來獲得路徑/文件名:C#獲取路徑/文件名由句柄(HWND)32位和64位

[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

唔...這行是錯誤的? – Mehrdad 2011-01-22 15:29:16

+0

return proc.MainModule.FileName.ToString(); – Ron 2011-01-22 15:32:22

+0

嘗試以管理員身份運行程序。 – 2011-01-22 15:33:14

回答

1

從您的問題看來,您目前已將您的程序編譯爲32位應用程序。但是,您試圖查詢的進程(假設您在64位版本的Windows上運行)無疑是64位版本。 That kind of thing isn't allowed。儘管您可以在64位版本的Windows上運行32位應用程序,但它們可以在Windows專用Windows(WOW64)子系統下運行。這就是爲什麼你得到一個Win32Exception聲稱「只有一部分ReadProcessMemory或WriteProcessMemory請求已完成」。我同意,如果您不知道Windows如何管理32位和64位進程,那麼它並不是最具描述性的錯誤消息,但憑藉這些知識,它至少可以更有意義。

的解決方案是編譯應用程序作爲64位應用程序(64),或用於「任何CPU」。之後,所有事情都應該按照預期工作。如果可能,我建議使用「Any CPU」,這將允許應用程序在32位操作系統上以32位模式運行,在64位操作系統上以64位運行。這是真正的情況下,理想的設置,假設:

  1. 你寫你的P/Invoke定義正確的(即使用IntPtr在適當情況下,而不是Integer)。
  2. 你不是依賴於編譯爲32位的第三方DLL(你沒有源代碼)。
1

我不知道跟這個有已知的問題的,它的氣味環境。該錯誤是非常低的水平,可能是仿真層。我只能建議你踢,並用不同的方式獲得相同的信息。您可以使用WMI,Win32_Process class。在ProcessId上運行選擇查詢,ExecutablePath屬性爲您提供您正在查找的內容。用W MI Code Creator utility實驗,它會自動生成你需要的C#代碼。然而,這種可能性不是零,這將以相同的方式失敗。

1

它適用於64x機器。到代碼中的唯一變化是檢查值,如:

if (hwnd != IntPtr.Zero) 
{ 
    if (pid != 0) 
    { 
     var p = Process.GetProcessById((int) pid) 
     if (p != null) 
     { 
      //... 
     } 
    } 
} 
0

這件事情檢查64位進程時,雖然不是那麼簡單,因爲這將是如果它是一個64絕對是可以從32位應用程序位編譯的應用程序:

[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; } 
    }