8

我有一个 C# 应用程序,它可以在 32 位和 64 位处理器上运行。我试图枚举给定系统上所有进程的模块,当尝试从 64 位应用程序枚举 32 位进程模块时,这会出现问题;Windows 或 .NET 禁止它。

我认为如果我可以从内部重新启动应用程序会非常酷,但强制它以 32 位运行,然后它会正确枚举上次运行时错过的进程模块。

如何以编程方式运行可执行文件并指示即使它是使用ANY CPU配置构建的,它也应该作为 32 位进程运行?

下面的代码会抛出一个System.ComponentModel.Win32Exception带有文本“A 32 bit processes cannot access modules of a 64 bit process”的信息。

[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);
                      }
                  //}
              }
          }
      }
  }
}
4

2 回答 2

3

根据 Rick Byer 的文章,AnyCPU Exes 通常比它们的价值更麻烦,用于启动 AnyCPU 应用程序的“位数”的决定是由操作系统加载程序决定的,你在这件事上没有任何发言权。

具体来说:

AnyCPU EXE 稍微复杂一些,因为操作系统加载程序需要决定如何初始化进程。在 64 位操作系统上,它们作为 64 位进程运行(除非“ldr64”主操作系统开关另有说明),而在 32 位操作系统上,它们作为 32 位进程运行。

因此,看起来您最好的选择是创建并启动第二个 32 位 exe 并启动它。

于 2013-07-27T00:15:42.370 回答
3

从外观上看,您的问题是在IsWow64Process不可用/不合适时发出调用....尝试使用以下代码进行检测:

当您克服了这一点后,您可以探索能够以与平台无关的方式列出 32 位和 64 位进程的模块的方法:

使用 WMI (Windows Management Instrumentation) 查询所需的信息...请参阅第 3 篇提到UseWMIToGetProcesses() 的帖子。

使用EnumProcessModulesEx(从 Vista 开始支持...当您检测到您处于 64 位模式时),因为它可以枚举 32 位和 64 位进程列表(请参阅此链接的最后):

用于CreateToolhelp32Snapshot枚举进程(在定义结构时必须小心):

于 2013-07-27T02:22:23.233 回答