2011-01-22 22 views
4

私はハンドルによって、パス/ファイル名を取得するには、次のコードを得た: ">それは32ビットで完璧に動作し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(); 
    } 

が、私は、64ビットでエラーが出ますReadProcessMemoryまたはWriteProcessMemory要求の一部だけが完了しました。 プロジェクトはx86(プラットフォームターゲットx86)としてコンパイルされます。

どうすれば修正できますか?

〜おかげロン

+0

hm ...どの行がエラーですか? – Mehrdad

+0

return proc.MainModule.FileName.ToString(); – Ron

+0

あなたのプログラムを管理者として実行してみてください。 –

答えて

1

それはあなたが現在の32ビットアプリケーションとしてプログラムをコンパイルしたあなたの質問から表示されます。しかし、照会しようとしているプロセス(64ビットバージョンのWindowsで動作していることを前提としています)は間違いなく64ビットです。 That kind of thing isn't allowed。 64ビットバージョンのWindows上で32ビットアプリケーションを実行することはできますが、Windows(WOW64)専用サブシステムで実行されます。そのため、「ReadProcessMemoryまたはWriteProcessMemoryリクエストの一部のみが完了しました」というメッセージがWin32Exceptionとなっています。 Windowsが32ビットと64ビットのプロセスをどのように管理しているのかわからないのであれば、もっとも記述的なエラーメッセージではないと私は同意しますが、この知識を踏まえれば、少なくとももう少し意味があります。

解決方法は、アプリケーションを64ビットアプリケーション(x64)として、または「任意のCPU」としてコンパイルすることです。それ以降はすべてが期待どおりに動作するはずです。可能であれば、32ビットOSでは32ビットモード、64ビットOSでは64ビットでアプリケーションを実行できる「Any CPU」を使用することをお勧めします。ものを想定し、実際の状況の理想的なセットです。

  1. あなたは(すなわち、代わりにIntegerの、IntPtr該当する場合を使用して)正しくP /起動定義を書きました。
  2. 32ビットとしてコンパイルされたサードパーティのDLL(ソースコードを持たないDLL)に依存しているわけではありません。
+0

私はこれが問題ではないと思います。私はちょうどこのコードを使用してサンプルWinFormsアプリケーションを作成しました。これはx86に対してコンパイルされ、Windows 7 x64で正常に動作しました。 –

+0

@ダリン:あなたはどのプロセスを尋問していますか?それが重要な問題になる可能性があります。質問者がアプリケーション用のウィンドウハンドルを渡しているかどうかは明らかではありません(これはあまり意味がありません;現在のアプリケーションでこの情報を取得する方がはるかに優れています)か、システム上の他のプロセス。 –

+0

@Darin Dimitrov、この関数を使用して、使用しているexeファイルのパスを抽出すると、それが動作します。しかし、別のexeファイルのパスを抽出しようとすると、このエラーが発生します。 – Ron

1

私はこれに関する既知の問題を認識していません、それは環境の匂いがします。エラーは非常に低レベルです、おそらくwow64エミュレーション層。私はちょうどあなたがパントし、同じ情報を得るために別の方法を使用することを提案することができます。 WMI、Win32_Process classを使用できます。 ProcessIdで選択クエリを実行すると、ExecutablePathプロパティによって、探しているものが得られます。実験にはW MI Code Creator utilityを使用して、必要なC#コードを自動生成します。オッズはゼロではないので、これは同じように失敗します。

+0

WMIは集中的な検索ですので、可能な限り避けてください。 – Wobbles

1

64xマシンではうまく動作します。コードへの変更のみのように、値をチェックしている:それは64だった場合、それは次のようになりほど単純ではないが、64ビットプロセスをチェックするとき

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

このことは、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; } 
    } 
関連する問題