Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I run an ANY CPU .NET executable programmatically in either 32-bit or 64-bit configurations?

Tags:

c#

.net

I have a C# application that is built to run on both 32-bit and 64-bit processors. I am attempting to enumerate the modules of all processes on a given system and this becomes problematic when trying to enumerate 32-bit process modules from a 64-bit application; Windows or .NET prohibits it.

I thought it would be pretty cool if I could re-launch the application from within itself, but force it to run as 32-bit, and then it would correctly enumerate the process modules it missed on the last run.

How can I run an executable programmatically and indicate that even though it was built with an ANY CPU configuration, it should run as a 32-bit process?

The code below throws a System.ComponentModel.Win32Exception with the text "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);
                      }
                  //}
              }
          }
      }
  }
}
like image 471
Michael J. Gray Avatar asked Jul 26 '13 23:07

Michael J. Gray


People also ask

How do I force an EXE to run in 32-bit mode?

if it is a shortcut you can right click and choose "open file location". Then right click the program, then click properties then go to the compatibility tab. Then check the box next to "Run this program in compatibility mode for:". Then choose which OS version to run it in compatibility mode for.

How do you tell if .NET application is 32 or 64-bit?

Run the application and launch the Task Manager to know if the process runs in 32-bit mode or 64-bit mode on a 64-bit machine. When "*32" is added to the 'image name', the process is running in 32-bit mode. Otherwise it is running in 64-bit mode.

Can a 32-bit application launch a 64-bit application?

The 64-bit versions of Windows don't provide support for 16-bit binaries or 32-bit drivers. Programs that depend on 16-bit binaries or 32-bit drivers can't run on the 64-bit versions of Windows unless the program manufacturer provides an update for the program.


1 Answers

By the looks of it your problem is with issuing the IsWow64Process call when it's not available/not appropriate....try doing your detection with this code:

  • http://1code.codeplex.com/SourceControl/changeset/view/39074#842775

When you get past that, you could then explore ways to be able to list the modules of 32bit and 64bit processes in a platform agnostic way:

  • http://blogs.msdn.com/b/greggm/archive/2005/11/10/491647.aspx

Use WMI (Windows Management Instrumentation) to query the required information...see the 3rd post down that mentions UseWMIToGetProcesses().

  • http://social.msdn.microsoft.com/Forums/en-US/491ea0b3-3e5b-4fa2-a2c3-2f1e485aed0c/enumerate-both-32bit-and-64bit-managed-processes

Use EnumProcessModulesEx (supported in Vista onwards...when you detect you are in 64bit mode) as it can enumerate the 32bit and 64bit process list (see very end of this link):

  • http://social.msdn.microsoft.com/Forums/vstudio/en-US/5e1323f9-986d-4abe-b545-ef04be5aaf58/how-do-i-enumerate-all-modules-of-a-wow64-process
  • http://msdn.microsoft.com/en-us/library/ms682633%28VS.85%29.aspx

Use CreateToolhelp32Snapshot to enumerate the Processes (you have to be careful in defining the structs):

  • http://msdn.microsoft.com/en-us/library/ms682489(v=vs.85).aspx
  • https://groups.google.com/forum/#!topic/microsoft.public.vb.winapi/SI7TY8Kb65E
like image 55
CSmith Avatar answered Sep 20 '22 11:09

CSmith