.NET Assembly Incorrect Format Error

"Could not load file or assembly 'ChilkatDotNet2, Version=9.3.0.0, Culture=neutral,
PublicKeyToken=eb5fc1fc52ef09bd' or one of its dependencies.
 An attempt was made to load a program with an incorrect format."

The “incorrect format” error is a 32-bit vs. 64-bit mismatch.  It means the application is trying to load a 64-bit .NET assembly into a 32-bit process,  or the reverse (a 32-bit assembly into a 64-bit process).

Possible solutions are:

1) Target your app for x86 instead of “Any CPU”.  If you do this, then your application will run as a 32-bit process regardless of the machine architecture and you may always use the 32-bit Chilkat assembly.

2) If you really need to target “Any CPU”, then make sure to deploy the 32-bit Chilkat assembly w/ your app on 32-bit systems, and deploy the 64-bit Chilkat assembly to 64-bit systems.

3) If your app is running within ASP.NET or a Windows Service and you’re not quite sure whether it’s 32-bit or 64-bit, then install the 32-bit Chilkat assembly in the 32-bit GAC (Global Assembly Cache), and also install the 64-bit Chilkat assembly into the 64-bit GAC.  The .NET runtime will automatically look in the correct GAC and will find the correct assembly.

Chilkat .NET for x64 (64-bit Windows)

The “An attempt was made to load a program with an incorrect format.” indicates that your program attempted to load a win32 assembly on an x64 Windows OS, or the reverse.

There is a separate Chilkat .NET assembly also named ChilkatDotNet2.dll for 64-bit Windows.  It may be downloaded at: http://www.chilkatsoft.com/downloads.asp This is for the 2.0/3.5 (or greater) Framework.  There is no x64 support for the .NET 1.0/1.1 Framework.

If you are developing on a 32-bit platform, but you need to deploy to a 64-bit platform, make sure that Visual Studio does not automatically copy the win32 ChilkatDotNet2.dll to the x64 target computer.  Your project may select “Any CPU” for it’s target platform, but you must deploy the correct ChilkatDotNet2.dll to the target computer.

Important: The 32-bit ChilkatDotNet2.dll can actually be used on both win32 and x64 systems, however, the EXE that loads the DLL (i.e. assembly) must be running as a 32-bit app. If you write a .NET application and target “Any CPU”, then it will run as a 64-bit application on an x64 computer, and therefore the x64 build of ChilkatDotNet2.dll would be required. However, if you target “x86” instead of “Any CPU”, then your application will run as a 32-bit app and the win32 build of ChilkatDotNet2.dll can be used on both 32-bit and 64-bit systems.

Beware of Version Mismatch: The version of the x64 Chilkat assembly must also match the version referenced by your Visual Studio project.  Otherwise you’ll get an assembly load-time error indicating a version mismatch.

Conditional Deployment: The Visual Studio Setup & Deployment project (.msi) is capable of conditional deployment.  This means you may include both win32 and x64 versions of ChilkatDotNet2.dll in your .msi, and the correct one is installed depending on the platform where it is run.  For more information:  MSI Conditional Deployment.

Windows Services: When using ChilkatDotNet2.dll from a Windows Serivce, the Chilkat assembly may need to be installed in the Global Assembly Cache (GAC).  This this blog post:  Using Chilkat x64 .NET Assembly in a Windows Service.

ClickOnce Deployment: See this blog post about x64 ClickOnce deployment.

GAC: Another solution is to put both x86 and x64 ChilkatDotNet2.dll’s in the GAC and let it decide when to use the x64 or the x86.

x64 ActiveX Registration on Windows 2008 Server

For the most part, a 32-bit Chilkat ActiveX DLL will run on a 64-bit computer. However, there is an issue (to be explained here) that requires the ActiveX to be built specifically for x64. Chilkat provides separate 64-bit ActiveX’s on it’s downloads web page, and these should be used on x64 systems.

The problem occurs when a method returns an ActiveX object. For example, the ChilkatMailMan2.CopyMail method returns a ChilkatEmailBundle2 object.

The registry in 64-bit versions of Windows is divided into 32-bit and 64-bit keys. (see http://support.microsoft.com/kb/305097) When a 32-bit Chilkat ActiveX creates the COM object to be returned, it uses the 32-bit registry keys. However, when the ActiveX was originally installed (using regsvr32 or Component Services) the 64-bit registry keys are created. Therefore, the internal error returned by Chilkat indicates that the ActiveX is not registered. It’s very confusing because it is possible to create the object via Server.CreateObject (in ASP) or CreateObject (in VBScript). This works because CreateObject is running in a 64-bit environment and is looking in the 64-bit registry keys. The problem occurs if a 32-bit DLL (or executable) calls CoCreateInstance internally to instantiate the ActiveX — in that case it fails because it’s looking in the 32-bit registry keys.

The solution: Make sure you use the x64 ActiveX’s on x64 computers, and the win32 ActiveX’s on 32-bit computers.

ChilkatDotNet2.dll on x64 from a Windows Service

Here’s the secret to getting the .NET runtime to load the ChilkatDotNet2.dll from a Windows Service: It must be installed in the GAC, but there’s a separate GAC for 64-bit assemblies:

(with permission from the Chilkat customer)
I was able to find a solution to this. I'm running a 64-bit version of
Vista, and there turns out to be a separate GAC for 64-bit assemblies, and
my application was searching there, and was not able to find the 32-bit
Chilkat assembly. I installed the 64-bit version in addition to the 32-bit
one in the GAC, and then the assembly loaded fine. Why this works when
running as a normal application but not when running as a service I don't
know, but at least it is working now.

Thanks for your excellent support!

This was the original error:

(with permission from the Chilkat customer)
> > Thanks for your immediate response. I tried to install the assembly in the
> > GAC, but it does not seem to help. I am able to load another GAC assembly
> > without problems:
> >
> > Assembly a = Assembly.Load("Microsoft.Practices.EnterpriseLibrary.Logging,
> > Version=2.0.0.0, Culture=neutral, PublicKeyToken=bf81d2044fa6b642");
> > Assembly b = Assembly.Load("ChilkatDotNet2, Version=8.7.0.0,
> > Culture=neutral, PublicKeyToken=eb5fc1fc52ef09bd");
> >
> > The first load does not throw an exception, but the second does:
> >
> > System.IO.FileNotFoundException: Could not load file or assembly
> > 'ChilkatDotNet2, Version=8.7.0.0, Culture=neutral,
> > PublicKeyToken=eb5fc1fc52ef09bd' or one of its dependencies. The system
> > cannot find the file specified.
> >
> > When turning on logging of the binding, it does not seem like the GAC is
> > searched at all, only the file system (current directory).
> >
> > I'm suspecting that this is a permission problem, but running the service as
> > LocalSystem or LocalService gives the same result.

System.BadImageFormatException

This usually happens when trying to use the Chilkat 32-bit .NET 2.0 Assembly on a 64-bit system. Download and use the x64 build for the Chilkat .NET 2.0 Framework at http://www.chilkatsoft.com/downloads.asp

Also, it’s likely that your development environment is 32-bit. You should add a reference to the 32-bit ChilkatDotNet2.dll, but deploy the 64-bit ChilkatDotNet2.dll to the x64 computer. Make sure the versions agree because the .NET runtime enforces version agreement.