Force .NET application to run in 32bit process on 64bit OS


Introduction

Our clients install our product on different environments. Some of them have 32bit server OS others have pure 64bit environments. Due to the lack of a 64bit version of a driver we use we have to run certain tools in 32bit mode. But since we do not want to have multiple versions of our product we had to find a possibility to force a .NET (command line) tool to run as a 32bit process on a 64bit OS (e.g. Windows Server 2003/2008).

Solutions

Set the platform target

The simplest solution is to set the Platform Target to be x86 on the project properties (build register).

image

This will cause the compiler to set the 32Bit flag in the CLR header of the corresponding assembly. Every time we run this application no matter on what type of OS it will execute as a 32bit process. But this solution although simple and straight forward was not a viable solution for us since – as mentioned above – we want to have one and only one version of our product. Thus all components of our package have to be compiled with Platform Target set to Any CPU.

Run in the context of IIS

If the application is running in the context of IIS then we can instruct IIS to run the application in a 32bit process. Of course this solution is not the right one for a command line tool…

To run a web application in 32bit mode on an 64bit OS open the IIS Manager and navigate to the application pool that the application should run in. Select the application pool and select “Advance Settings…”. In the Advanced Settings dialog set the “Enable 32-Bit Applications” to true.

image

Use corflags.exe to set the bitness

You can flip the 32-bit flag on the assembly after-the-fact using a tool called CorFlags.exe, but that’s probably not a good idea for a long-term sustainable option. For the details about how to use CorFlags.exe see this link. E.g. to set the 32Bit flag open the Visual Studio command prompt, navigate to the directory where your assembly is and use this command

CorFlags.exe MyAssembly.exe /32Bit+
</p>

and to turn off  the 32Bit flag it would be

CorFlags.exe MyAssembly.exe /32Bit-
</p>

Create a shallow wrapper application

The solution we finally adapted was to build a shallow wrapper application whose platform target is set to x86 and which does nothing else than call the respective application. As already mentioned earlier the application is a command line tool and as such has an entry point defined as follows

public class Program
{
    public static int Main(string[] args)
    {
        // ...
    }
    
    // more code
}
</p>

Our wrapper application can now reference the wrapped application and execute it by using this code

class Program32
{
    static int Main(string[] args)
    {
        return Program.Main(args);
    }
}
</p>
Since the “bitness” of the starting assembly determines the “bitness” of the process the whole application will run in a 32bit process.

</p> </p>

But as always, having a solution makes you want to have more. What if we could create a generic 32bit wrapper application that can call any (command line) tool and force it to run in a 32bit process?

Something like this:

RunAs32Bit.exe /assembly:MyAssembly.exe /params:"/connection:Oracle1 /user:joe /numThreads:4"
</p>

What we finally came up is as simple as this

static int Main(string[] args)
{
    // load the assembly
    var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var assemblyName = Path.Combine(directory, args[0].Substring(10));
    var assembly = Assembly.LoadFile(assemblyName);
 
    // find the entry point of the assembly
    var type = assembly.GetTypes().FirstOrDefault(t => t.GetMethod("Main") != null);
    var mi = type.GetMethod("Main");
 
    // call the entry point of the wrapped assembly and forward the command line parameters
    var arguments = args[1].Substring(8).Split(' ');
    var list = arguments.Where(a => a.Trim() != "").ToArray();
    return (int)mi.Invoke(type, new object[] { list });
}
</p>

Note that for brevity I omitted the code to validate the command line parameters.

Leaving Switzerland