2013-07-26 81 views
8

我有一個C#應用程序,可以在32位和64位處理器上運行。我試圖枚舉給定系統上所有進程的模塊,當嘗試枚舉來自64位應用程序的32位進程模塊時,這會變得有問題; Windows或.NET禁止它。如何在32位或64位配置中以編程方式運行ANY CPU .NET可執行文件?

我認爲如果我可以從本身重新啓動應用程序,但強制它以32位運行,然後它會正確枚舉它在最後一次運行時錯過的過程模塊,這將非常酷。

如何以編程方式運行可執行文件並指出即使它是使用ANY CPU配置構建的,它應該作爲32位進程運行?

下面的代碼將文本「32位進程無法訪問64位進程的模塊」引發System.ComponentModel.Win32Exception

[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool IsWow64Process(
    [In] IntPtr hProcess, 
    [Out] out bool lpSystemInfo); 

private static void Main() 
{ 
    Process[] processes = Process.GetProcesses(); 

    using (FileStream fileStream = new FileStream("ProcessModulesDump.dat", FileMode.Create, FileAccess.Write, FileShare.None)) 
    { 
     using (GZipStream gzipStream = new GZipStream(fileStream, CompressionLevel.Optimal)) 
     { 
      using (TextWriter writer = new StreamWriter(gzipStream)) 
      { 
       foreach (Process process in processes) 
       { 
        writer.WriteLine("{0} - {1}", process.Id, process.ProcessName); 

        //bool lpSystemInfo; 
        //if ((Environment.Is64BitProcess && 
         IsWow64Process(process.Handle, out lpSystemInfo)) || 
         (!Environment.Is64BitProcess && 
          !IsWow64Process(process.Handle, out lpSystemInfo))) 
        //{ 
         foreach (ProcessModule module in process.Modules) 
         { 
          writer.WriteLine("\t{0} - {1} ({2})", 
           module.BaseAddress, 
           module.ModuleName, 
           module.FileName); 
         } 
        //} 
       } 
      } 
     } 
    } 
} 
+0

向我們展示您用來枚舉過程的代碼,並告訴我們您收到的錯誤消息的準確措辭。 –

+0

你可以通過啓動一個32位的助手可執行文件來解決這個問題嗎?它可以加載並運行真正的可執行文件,就像它是一個庫一樣? – hvd

+0

@ hvd的確我可以。我想避免使用兩個可執行文件,並且認爲如果您可以在啓動過程中設置某種選項來指示它應該被強制以32位運行時,它會很整潔。 –

回答

3

通過它的外觀你的問題是發出IsWow64Process通話時,它不是可用/不可適當....嘗試做你的檢測與驗證碼:

當您可以通過以下方式探索如何以平臺不可知的方式列出32位和64位進程模塊:

使用WMI(Windows管理規範)來查詢所需信息...看到第三下來後說提到UseWMIToGetProcesses()。

使用EnumProcessModulesEx(在Vista中支持起...當你發現你是在64位模式),因爲它可以枚舉的32位和64位的進程列表(見這個鏈接的盡頭):

使用CreateToolhelp32Snapshot枚舉流程(你必須要小心在定義結構):

+0

我的回答(自刪除以來)基本上是您的第一點,WMI僅適用於進程而非其模塊。 –

3

據裏克·拜爾的文章,AnyCPU Exes are usually more trouble than they're worth上用於啓動AnyCPU應用程序的「位數」的決定是由OS加載器決定,你沒有在這個問題上有發言權。

具體做法是:

AnyCPU EXE文件是一個有點複雜,因爲操作系統加載程序需要 決定如何initialze過程。在64位操作系統上,它們作爲 64位進程(除非'ldr64'主操作系統開關另有說明), 和32位操作系統上運行,它們作爲32位進程運行。

因此,它看起來像你最好的選擇是創建並啓動第二個32位的EXE並啓動這一點。

+0

一種方法是將代碼移入單獨的類庫程序集(保留它爲AnyCPU) - 然後創建兩個應用程序(一個x86,一個x64),並讓它們都調用類庫來執行工作。 .exe會導致您的進程以所需的「位」運行,並且類庫會在運行時進行JIT編譯,以適應.exe所需的風格。 –

相關問題