How to run 32 bit .NET Windows apps on 64 bit Windows (including with IEExec)

Posted on Updated on

Suppose you have a 32 bit .NET Windows application (whether it is a console or GUI Windows application (the latter in .NET a so-called Windows Forms app)) and you want to run it on a 32 bit Windows system. It doesn’t matter if you start it from Windows Explorer, from Command Prompt, from PowerShell (PS), through ClickOnce or start it directly from Internet Explorer (IE). In the last case IEExec.exe is started and your 32 bit .NET (version 1, 2 or 3) application is run within this process. IEExec is a runtime host for .NET (version 1, 2 or 3) applications in the scenario where the .NET executable is referred to via an URL provided to IE. For example, suppose you have a .NET GUI application hosted on a web server (no no, I’m not talking about a .NET WUI application, I am talking about a .NET GUI application (an .exe file and possibly a few DLLs) hosted by a web server like IIS, just like any other kind of file can be hosted by a web server. This type of deployment is called No-Touch Deployment aka Zero Deployment). The URL is something like http://servername:port/vdir/application.exe. You open IE, type or paste this URL in the address bar and let IE do its job. The IEExec.exe process will be created and the application.exe will run within this process, as IEExec is the runtime host in this scenario.

So far so good. But what if we want to run our application on a 64 bit Windows. Let’s see what happens if we open Windows Explorer and browse to the location of application.exe. We open the executable from within Windows Explorer and what happens next depends. If your application has been built for x86 (32 bit), it will run fine. Windows sees it’s dealing with a 32 bit application and thus it will run like any other 32 bit application on a 64 bit Windows. If your application was compiled for “Any CPU”, Windows will try to run it as a 64 bit application. This shouldn’t be a problem, except when your application isn’t really 64 bit compatible, for example when you use a 32 bit Oracle driver. In this case compiling to “Any CPU” was a bad decision, you must have compiled for 32 bit only. The solution in this scenario is to recompile or, if not possible, corflag the executable. By using the CorFlags Conversion Tool (CorFlags.exe) you can mark a .NET executable explicitly as a 32 bit application, just as you would have compiled it for 32 bit only (you only need to corflag the .exe files, not necessarily the DLL assemblies). Problem solved, right? Well, yes and no. If you start the application in Windows Explorer: yes. If you browse to the application through IE: no. IE will start IEExec.exe, which will try to run the for 32 bit compiled or corflagged application, but this will definitely fail, i.e. with a Microsoft IE Execute shell dialog box telling you the exception System.BadImageFormatException has been thrown (see the screenshots below). It doesn’t matter if you do this from the 32 bit or 64 bit version of IE.



This seems very weird, doesn’t it? You have a .NET application which is made explicitly for 32 bit (by compiling or corflagging), you can start it as a 32 bit application no matter how you start it (from Windows Explorer for example), even on a 64 bit Windows system, but this fails when you start it from (32 bit or 64 bit) IE on a 64 bit Windows system. Huh? Don’t panic, your application is fine and you don’t experience a virus or a bug 🙂 The thing is the 32 bit version of IE starts an IEExec.exe from the 32 bit Framework folder (C:\Windows\Microsoft.NET\Framework), while the 64 bit version of IE starts an IEExec.exe from the 64 bit Framework folder (C:\Windows\Microsoft.NET\Framework64). All IEExec.exe files are compiled for “Any CPU”, which means that IEExec.exe always starts as a 64 bit process on a 64 bit Windows. This means a 64 bit runtime host should start and run a 32 bit .NET application and that’s why IEExec.exe sees a bad image format and throws an exception of the type System.BadImageFormatException. And that’s also why the fact that you used a 32 bit IE didn’t make a difference; the error has nothing to do with IE! Note: there could be other causes for this exception, so getting this exception doesn’t necessarily mean a 64 bit IEExec tried to run a 32 bit application! Another cause could be that your application runs as 64 bit, but refers to a 32 bit unmanaged DLL. For still other causes and more information, check the Remarks section of this MSDN page: http://msdn.microsoft.com/en-us/library/system.badimageformatexception.aspx.

If you read this article, the chance exists you experience this error, right? And the previous piece of text doesn’t probably interest you, right? You have searched the Net for hours trying to find a solution and you’re quite desperate. Right? Well, prepare for relief! The only way to workaround this problem is to corflag IEExec.exe. Why? Well, if you corflag IEExec.exe to mark it explicitly as a 32 bit only application, it will always run as a 32 bit application, even on a 64 bit Windows system. And a 32 bit runtime host is just what we need to run our 32 bit .NET application! I must stress the fact that you only have to corflag IEExec.exe when your application is started from IE: if you start it from Windows Explorer, the command line,… IEExec.exe isn’t used at all!

Be aware of the fact that this is a workaround, not a real solution. You are tampering an official Microsoft file and that’s never Microsoft’s intention. So in a way your system isn’t 100% clear anymore. Secondly, I think this also means this isn’t supported by MS, so if you need to open a support call… Last but not least, your security is reduced. Yup, the thing is IEExec.exe is digitally signed by Microsoft and if you corflag the file, then you’re actually changing the file, making the digital signature invalid. You’re still able to run IEExec, but it’s not secured by a digital signature anymore. If your IEExec.exe is replaced by a malicious piece of software, you probably won’t even notice and even if you do it could be already too late… Because of these reasons I strongly advise not to corflag IEExec.exe, except when you don’t have another choice. For example, if you can’t make your application completely 64 bit compliant (in time or at all) and it must definitely run on 64 bit Windows (on the company’s new 64 bit RDSH environment for example) and your applications are started through IE (consider another way to start up your software though!), then I guess you don’t have a real choice: corflag IEExec.

You should ask yourself which IEExec.exe files to corflag, because probably several of these files exist on your system. First of all, there is a chance you have different versions of .NET Framework installed; some of them have their own IEExec.exe files. Secondly, some versions have a 32 bit and 64 bit folder. This means there is a decent chance you have more than 1 folder with an IEExec.exe file. Create an inventory of all the applications that need IEExec (that is, every application that should be able to start from IE) and that should run as 32 bit. Find out the highest version of the .NET Framework needed. For this version you need to corflag IEExec.exe. A second choice to make is for which IE (x86 or x64) you want the exe corflagged. Corflag the IEExec of the 32 bit Framework folder if you want to be able to start your application(s) from the x86 IE, just like you must corflag the IEExec of the 64 bit Framework folder if you need to be able to start your application(s) from the x64 IE.

Be aware though that corflagging IEExec for 32 bit means IEExec can’t run anymore as a 64 bit application and thus can’t host 64 bit .NET applications anymore. For example, suppose you corflag the IEExec.exe files for .NET Framework 2.0 as 32 bit only. If you start a 64 bit .NET application from IE made for .NET Framework 2.0, the application will fail to run. If you start the 64 bit application through another way (Windows Explorer for example) or if the 64 bit application needs another version of the Framework, then you shouldn’t experience any problem. One thing you could do is corflag the IEExec.exe of the 32 bit framework folder and leave the IEExec.exe file of the 64 bit framework folder alone. This way you can start 32 bit .NET apps through the 32 bit IE and still run 64 bit .NET apps through the 64 bit IE (or even the other way around if you want, depending on how you like it). If you don’t want to explain your users how, when and why they need to open different Internet Explorers for different applications, then you’re screwed 🙂 Or you could provide them with shortcuts, so they don’t have to open IE explicitly, let alone know which IE to open for which application.

Some background information

The CorFlags Conversion Tool (CorFlags.exe) was introduced with .NET Framework 2.0 and can be found in the Microsoft Windows SDK. The last version of this SDK is 7?1, also called “Microsoft Windows SDK for Windows 7 and .NET Framework 4”. To mark a file as 32 bit explicitly you need to use the switch “/32BIT+” and to remove this mark you use the switch “/32BIT-“ (both without the quotes). A file can only be corflagged if it’s a .NET assembly. If the assembly is strong named (signed), you must also use the “/Force” switch. After corflagging it’s advisable of course to resign the assembly, except when you really can’t do this (like with IEExec.exe for example). The latest version of the SDK (at the time of writing) can be found in the Microsoft Download Center: http://www.microsoft.com/downloads/en/details.aspx?familyid=6b6c21d2-2006-4afa-9702-529fa782d63b&displaylang=en.

Starting from Vista extra security measures are implemented in Windows. Replacing the IEExec.exe file just doesn’t work by default, even if you’re an administrator. First of all you need to take ownership of the file and then you need to give you the necessary permissions (for example, Full control). Then you can deal with the file the way you want. This way you can delete the file and copy or move the corflagged IEExec.exe (which you had copied earlier to a temporary location where you’ve corflagged it) to the framework folder. Remember to set the permissions to the original permissions again:
• SYSTEM: “Read & Execute” and “Read”
• Administrators: “Read & Execute” and “Read”
• Users: “Read & Execute” and “Read”
• TrustedInstaller: “Full control”
TrustedInstaller can be added to the ACL by typing the account “NT SERVICE\TrustedInstaller” for the “computer domain”. Also, make TrustedInstaller again the owner of the file.

IEExec.exe is in fact a quite undocumented application from Microsoft, part of the .NET Framework. IE 5.01 and later download assemblies to the assembly download cache and create a new IEExec.exe process to run the executable reffered to by the URL (possible files related to this program are then downloaded too, including possible DLL assemblies). IEExec sets up a runtime environment with constrained security, just as IE knows this (for example, the concept of zones is used in IEExec.exe too, what explains why .NET applications referred to through IE have another way of starting up: to get a typical “IE environment”, which is different than the default environment). If you want such an environment with constrained security without having to go through the browser process, you can run IEExec.exe from the command line and providing the URL as a parameter (perhaps you could even provide users with shortcuts for those commands instead of shortcuts to IE). IEExec.exe from .NET Framework 1.0 can receive extra parameters like the desired zone, but starting from .NET Framework 1.1 only the URL is accepted as a parameter. The latest version (2.0.50727.4927) belongs to .NET Framework 2.0 and is used for later versions of the .NET Framework (3.0 and 3.5) till the introduction of .NET Framework 4.0, which doesn’t support this mechanism anymore.

Greetz,
Pedro

Advertisements

9 thoughts on “How to run 32 bit .NET Windows apps on 64 bit Windows (including with IEExec)

    DaveC said:
    07/06/2011 at 08:57

    "After corflagging you must of course resign the assembly, except when you really can’t do this (like with IEExec.exe for example). " – Well this is exactly the exe that you have been talking about corflagging!! Can we have some sort of workaround. I am completely enable to get around strong name signing with IEExec.exe

    Pedro said:
    09/06/2011 at 12:47

    I guess I wasn't very clear in what exactly I meant. Technically you can corflag a signed assembly (like IEExec.exe), but by doing this you will lose the digital signature and you end up with an unsigned (but corflagged!) assembly. This unsigned assembly will still run in a typical, normal situation. With other words: if you corflag IEExec.exe (which is signed), you get an unsigned but corflagged IEExec.exe that will run just fine.There are 2 remarks:1) when .NET code access policies are configured by administrators in such a way that the running of unsigned assemblies is prohibited, it won't run anymore of course (well, not on systems where those policies are valid, that is).2) you lose a little bit of security, as you now get an extra file that's unsigned.Because of those 2 remarks it's advisable to resign the originally signed assembly you have corflagged. You can do this for applications developed in your company (because you or someone else has the key or code signing certificate to do this), but of course you can't do this for applications from other companies (like Microsoft). IEExec.exe is such an example: it was signed by MS, so you can't resign it (of course you can't!). An extra remark for 3rd party assemblies is the fact you probably lose support rights.The bottom line is you need to make the choice yourself: do I really need to corflag IEExec.exe (and thus losing its signature, losing support rights and perhaps changing .NET code access policies) or will I keep security and/or support rights and/or .NET code access policies at the maximum level (so not corflagging IEExec.exe)?I guess I made a linguistic error with "you must of course resign"; what I actaully meant was "it's advisable of course to resign". So technically there is no "must" 🙂 In the meantime I've changed the sentence in my article to reflect better what I mean.I hope this is an answer to your question? If not, please don't hesitate to tell me so and I'll try to explain it better.Ciao!Pedro

    Anonymous said:
    24/09/2011 at 08:51

    I have the same problem running a program which is a marked as 32 Bit application. After testing around some time i noticed that the exception is only raised when the program downloaded from "local intranet" zone. So i changed the url from http://downloadserver/vdir/app.exe to something that has a "." in there: http://download.server/vdir/app.exe and without any other action it works.

    Anonymous said:
    21/10/2011 at 13:30

    I recently converted my 32 bit .NET 2.0 application to 32 bit .NET 4.0. I am getting this issue and really do not understand why I would have to coreflag the IEEXEC when I didn't have in my 32 bit .NET 2.0 application?

    Pedro said:
    05/11/2011 at 22:43

    To Anonymous (from September 24): are you sure you're getting a System.BadImageFormatException and not another exception or error within the local Intranet zone? It seems weird zone settings (~security settings) would raise an exception mentioning a bad image format… I do know zone settings are indeed an important factor to be able to run (.NET) applications via IE, but I'm not aware of any influence of those zone settings on which IEExec is used, how it runs and other image formats… Can you double-check this please? Thanks!

    Pedro said:
    07/11/2011 at 19:55

    "Anonymous" (the one from October 21), do you run or try to run your "old" and "new" application on a 64 bit Windows? If so, do you try to run your application through a browser? If so, which browser do you use? IE? 32 of 64 bit IE? Personally I had the experience with .NET 2.0 applications and I've never tried it with .NET 4.0 applications… But AFAIK starting from .NET Framework 4 the IEExec.exe mechanism isn't supported anymore! Perhaps you have compiled the "old" application (.NET 2.0) for "Any CPU" and the "new" application for 32 bit? If so, this would explain your symptoms: IEExec can handle your "Any CPU" .NET 2.0 app (as it's compiled for Any CPU), while it can't deal with your newer 32 bit only application version (although, again, I thought the IEExec way is only supported till 3.5…). Perhaps your error isn't related to IEExec with your .NET 4.0 application…? Can you check these things out? Ciao!

    Anonymous said:
    17/11/2011 at 20:25

    To Petro (5. November): zone settings are default. The problem occured after update to Win7/Win2k8R2 SP1 and IE 9

    Anonymous said:
    15/04/2012 at 15:24

    We resolved our issues by insuring the security.config file was the same in ALL of the framework directories.

    windows phone 7.5 app development tutorial said:
    19/10/2013 at 05:31

    There is definately a lot to know about this issue.
    I really like all of the pooints you’ve made.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s