Tech Off Thread

11 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

How to programmatically start a .Net exe as either 32-bit or 64-bit?

Back to Forum: Tech Off
  • User profile image
    BitFlipper

    If you create a .Net exe and you set the target platform as "Any CPU", the exe will of course automatically run as either 32-bit or 64-bit, depending on what the platform is.

    For the purpose of this question, let's say I am always running on a 64-bit OS since this is a non-issue on a 32-bit OS. What I want to do is to start a .Net exe from another .Net exe and be able to specify whether the exe I'm starting up (which was compiled with "Any CPU") should run as either 32-bit or 64-bit. I looked at ProcessStartupInfo but I didn't see anything that allowed me to specify the preferred "bitness" of the exe I want to start.

    Any ideas?

  • User profile image
    W3bbo

    It's a hack, but I had this problem a short while ago. My solution was to use reflection.

    I wrote a simple 15-line program that loads an assembly and gets the EntryPoint MethodInfo, it then invokes it.

    The targeted assembly will then load under the ISA of my 'starter motor' program.

    public static void Main(String[] args) {
    
    if( args.Length < 1 ) return;
    if( !File.Exists( args[0] ) ) return;
    
    Assembly target = Assembly.LoadFrom( args[0] );
    MethodInfo ep = target.EntryPoint;
    if( ep == null ) return;
    
    String[] oArgs = new String[ args.Length - 1 ];
    Array.Copy( args, 1, oArgs, 0, args.Length - 1 );
    
    ep.Invoke( null, oArgs );
    
    }

  • User profile image
    BitFlipper

    W3bbo, I'm not following.

    Let's say I have two executables, Foo.exe and Bar.exe. Let's say my OS is 64-bit, and Foo.exe always runs as 64-bit. But Bar was compiled with "Any CPU", so it can run as either a 32-bit or a 64-bit exe. Now what I want to do is programmatically run Bar.exe from within Foo.exe, but I want to have the ability to specify that Bar.exe must run as either a 32-bit exe, or as a 64-bit exe.

    How can I do that?

  • User profile image
    Sven Groot

    W3bbo's suggestion is to have two "bootstrap" .Net exe's, one 32 bit and 64 bit, that will invoke the entry point of the specified application. Foo.exe would invoke one of these exe's and tell it to load Bar.exe, rather than invoking Bar.exe directly.

  • User profile image
    BitFlipper

    OK, I understand. Not ideal since now there would be four exes involved as opposed to just two (Foo.exe, Bar.exe, Loader32.exe, Loader64.exe), but at least Bar.exe doesn't have to be compiled twice, just the bootloader exes.

    Even so, it is not a bad solution given that apparently there is no other way to do this.

  • User profile image
    cheong
    Recent Achievement unlocked: Code Avenger Tier 4/6: You see dead program. A lot!
    Last modified
  • User profile image
    W3bbo

    , BitFlipper wrote

    OK, I understand. Not ideal since now there would be four exes involved as opposed to just two (Foo.exe, Bar.exe, Loader32.exe, Loader64.exe), but at least Bar.exe doesn't have to be compiled twice, just the bootloader exes.

    Even so, it is not a bad solution given that apparently there is no other way to do this.

    I think there might be another way. IIS lets you specify if the application pool processes run as 32-bit or 64-bit, so maybe there's some magic going on there? The relevant portions of IIS are managed, so see if Reflector turns anything up.

  • User profile image
    Dexter

    IIS's worker process (w3wp.exe) exists in both 32 and 64 bit versions so it looks pretty much like your original solution. Win32 API doesn't seem to have a way to specify the bitness of a process but that's not surprising, only .NET executables have this "AnyCPU" property and the OS doesn't know much about .NET.

  • User profile image
    BitFlipper

    @cheong:

    Thanks for those links. Unfortunately those seem to be related more to forcing pre-existing applications to run as 32-bit as opposed to forcing an application at runtime to run as either 32-bit or 64-bit. It looks like they fiddle with corflags, which is something I have done extensively in the past. See this thread that contains the code of my utility that allows you to create 32-bit and 64-bit versions of exes that can be called directly from unmanaged code by using a new attribute called DllExport (reverse P/Invoke, but with no intermediate C++/CLI dll required). This utility also fiddles with corflags. This makes it just as easy to export managed methods as native functions as it is to import native functions from DLLs.

    @W3bbo:

    You gave me an idea... It should be possible to create two additional projects, one called Loader32.exe (target x86), and the other called Loader64.exe (target x64) just like you say, and make the Bar.dll project (target Any CPU) a dependency in both of the loader projects. Then I just need to call some method in Bar.dll from either of the loader EXEs and it won't be a "hack" as you mention.

    I think your solution would work well if Bar.exe was an externally acquired application, but since I am developing it, I can easily make it a DLL as opposed to an EXE.

  • User profile image
    cheong

    @BitFlipper: From my understanding, the corflags solution works because by specifying "AnyCPU" when you compile, your source is compiled to MSIL assembly. And just before it runs, NGen will compile the assembly to actual code to run as it sees fit. The "flag" in the EXE header just force the decision to be 32-bit. Nothing is different than having a custome loader to speciy whether to run something as 32/64 bit except that it requires changes to the origional file, which might not always possible (especiallly in UAC enabled machine that only TrustedInstaller have write access to "Program Files" folder.)

    So yes, having 2 seperate loader is generally better approach.

     

    Recent Achievement unlocked: Code Avenger Tier 4/6: You see dead program. A lot!
    Last modified
  • User profile image
    BitFlipper

    @cheong:

    Yep I agree with you. With my previous dealings with corflags, I know all too well about what you mention (see the link I provided). What I did in that case was to have a post-build step that decompiles the DLL into MSIL and then recompiles it again, once with corflags set for 32-bit, and once for 64-bit. I needed to do that because in that case my DLL was being loaded by unmanaged code, and to unmanaged code the DLL must either look like a 32-bit DLL or a 64-bit DLL, even though nothing other than the corflags were different between the two DLLs.

    Just note that I never suggested that for my current problem I want to twiddle the corflags. When I said "programmatically", I literally mean I want to start one executable as 32-bit and then the same executable again as 64-bit from code. I don't want to twiddle corflags at that point. I don't think I can twiddle with the corflags while the previous process is still running unless I first make a copy of the exe, but that just gets too complicated.

    Right now my solution is to simply have a main executable called Bar.dll, and then have two loader exes, one called Bar32.exe (x86) and Bar64.exe (x64). All I do in each loader is:

    static void main(string[] args)
    {
        var someClass = new SomeClass();
        someClass.Run();
    }

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.