Reputation: 9896
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);
}
//}
}
}
}
}
}
Upvotes: 8
Views: 1785
Reputation: 12540
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):
Upvotes: 3
Reputation: 44921
According to Rick Byer's article, AnyCPU Exes are usually more trouble than they're worth, the decision on the "bitness" used to launch AnyCPU applications is determined by the OS loader and you don't have any say in the matter.
Specifically:
AnyCPU EXEs are a little more complicated since the OS loader needs to decide how to initialze the process. On 64-bit OSes they are run as 64-bit processes (unless the 'ldr64' master OS switch says otherwise), and on 32-bit OSes they are run as 32-bit processes.
So, it looks like your best option is to create and launch a second, 32-bit exe and launch that.
Upvotes: 3