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);
}
//}
}
}
}
}
}
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.
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.
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.
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:
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:
Use WMI (Windows Management Instrumentation) to query the required information...see the 3rd post down that mentions UseWMIToGetProcesses
().
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):
Use CreateToolhelp32Snapshot
to enumerate the Processes (you have to be careful in defining the structs):
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With