.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.

Using regsvr32 to Register a 32-bit ActiveX or 64-bit ActiveX on Windows 64-bit System

A 64-bit Windows system has two separate registries — one for 32-bit processes, and one for 64-bit processes. The reason for this is simple: Let’s say your application instantiates an instance of an ActiveX component by calling CreateObject(“Chilkat.Ssh”). If your application is running in a 32-bit address space, the registry entries for “Chilkat.Ssh” should point to a 32-bit DLL in the filesystem. However, if your application is running in a 64-bit address space, the registry entries should point to a 64-bit DLL. The only possible way to do it is to have separate registries — one for 32-bit and one for 64-bit.

On a Windows 64-bit computer, the regsvr32 program (located in \windows\system32) is a 64-bit program that registers a 64-bit ActiveX DLL using the 64-bit registry. For example:

regsvr32 ChilkatSsh_x64.dll

On Windows x64, regsvr32 expects a 64-bit DLL and updates the 64-bit registry.

To register a 32-bit ActiveX DLL in the 32-bit registry, you’ll need to run the regsvr32 located in \windows\syswow32. For example:

cd \windows\syswow64
regsvr32 c:\ChilkatSsh.dll

It’s important to know whether the program that will be loading the ActiveX is 32-bit or 64-bit. For example, IIS on Windows 64-bit can run as either. If IIS is running in 32-bit mode, any ActiveX’s used in your ASP pages should be 32-bit DLL’s registered in the 32-bit registry. Likewise for 64-bit.

The same conditions apply for other environments, such as SQL Server 2008. Is the database server running as a 32-bit process or 64-bit process? If an ActiveX is used within a stored procedure, make sure the appropriate DLL is registered to the appropriate registry…

Using 32-bit or 64-bit ActiveX Components on x64 Windows

64-bit Windows is capable of running applications in both 32-bit mode and 64-bit mode.
If the application process is running in a 32-bit address space, the DLL must also use a 32-bit address space. (In other words, it should be a DLL compiled for the Win32 platform.) If the application process is running in a 64-bit address space, the DLL’s address space must match — i.e. it should be a DLL compiled for the x64 platform. Just because your application is running on 64-bit Windows does not mean it requires a 64-bit DLL — the determining factor is the process’s address space.

For example, let’s say you’ve configured IIS to run its worker processes in 32-bit mode. In that case, your ASP apps would require 32-bit DLLs. If IIS is running in 64-bit mode, then 64-bit DLLs are needed.

About the Windows registry and ActiveX:

A 64-bit Windows system has two separate registries — one for 32-bit processes, and one for 64-bit processes. The reason for this makes sense if you think about it.. Let’s say your application instantiates an instance of an ActiveX component by calling CreateObject(“Chilkat.Ssh”). If your application is running in a 32-bit address space, the registry entries for “Chilkat.Ssh” should point to a 32-bit DLL in the filesystem. However, if your application is running in a 64-bit address space, the registry entries should point to a 64-bit DLL. How can you do both with one registry? The answer is to have separate registries — one for 32-bit and one for 64-bit.

Therefore, when you register a DLL with regsvr32 — did you register the 32-bit DLL in the 32-bit registry, or did you register the 64-bit DLL in the 64-bit registry? You’ll need to get it right. When you run regsvr32 on an x64 system, you’re running the 64-bit version by default. (That’s a bit confusing because of the “32” in the regsvr32 name…) To run the 32-bit regsvr32, do this:

cd \windows\syswow64
regsvr32 c:\filename.dll

(Note the stupidity of it all — the default regsvr32 is 64-bit and resides in the \windows\system32 directory. Note the “32” in system32 and the “32” in regsvr32 — quite misleading. However the 32-bit version of regsvr32 is found in the \windows\syswow64 directory. Note the “64” in the directory name. That’s also misleading. Ughhh!)

More information about: regsvr32 or ActiveX object creation errors.

Incorrect Format Error when trying to load .NET Assembly

This Chilkat blog post explains the following error:

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

When a DLL is loaded, it is mapped into the process’s address space. If the process is running in a 32-bit address space, the DLL must also use a 32-bit address space. (In other words, it should be a DLL compiled for the Win32 platform.) If the process loading the DLL is running in a 64-bit address space, the DLL must match — i.e. it should be a DLL compiled for the x64 platform.

This applies to both .NET assemblies *and* ActiveX DLLs.

64-bit Windows is capable of running applications in both 32-bit mode and 64-bit mode. If your application is running in a 32-bit address space, the DLLs it loads must also be 32-bit. If your application is running in a 64-bit address space, the DLLs it loads must also be 64-bit. Just because your application is running on 64-bit Windows does not mean it requires a 64-bit DLL — the determining factor is the process’s address space.

For example, let’s say you’ve configured IIS to run its worker processes in 32-bit mode. In that case, your ASP or ASP.NET apps would require 32-bit DLLs. If IIS is running in 64-bit mode, then 64-bit DLLs are needed.

Important: The “Incorrect Format” error is only caused by one thing: The address space (32-bit or 64-bit) of the process loading a DLL does not match the DLL’s address space. Quite often developer get stuck on this problem because they don’t know one or both of the following:

  1. Is your application running in a 32-bit address space or 64-bit?  You’ll need to know this.  If running in 32-bit, you can ignore the 64-bit DLL builds altogether because you’ll never need them.  For .NET applications in Visual Studio you may target “win32” instead of “Any CPU” to force your executable to run in a 32-bit address space.  In 99% of all cases, this is not an issue — does your application really need more than 4GB of memory?
  2. You’re not loading the DLL you *think* your loading.  With ActiveX, are the registry entries created by regsvr32 really pointing to the DLL in the filesystem that you’re intending to use?  (For more information: regsvr32 registry entries)  With .NET, is the assembly found by the .NET runtime loaded from the GAC?  Is it found in the directory where you think it should be found?

About the Windows registry and ActiveX:  The following applies only to ActiveX DLLs and not .NET assemblies.  .NET assemblies are not registered with regsvr32 and have no registry entries required for locating the DLL when loading.

A 64-bit Windows system has two separate registries — one for 32-bit processes, and one for 64-bit processes.  The reason for this makes sense if you think about it..   Let’s say your application instantiates an instance of an ActiveX component by calling CreateObject(“Chilkat.Ssh”).   If your application is running in a 32-bit address space, the registry entries for “Chilkat.Ssh” should point to a 32-bit DLL in the filesystem.  However, if your application is running in a 64-bit address space, the registry entries should point to a 64-bit DLL.  How can you do both with one registry?  The answer is to have separate registries — one for 32-bit and one for 64-bit.

Therefore, when you register a DLL with regsvr32 — did you register the 32-bit DLL in the 32-bit registry, or did you register the 64-bit DLL in the 64-bit registry?  You’ll need to get it right.  When you run regsvr32 on an x64 system, you’re running the 64-bit version by default.  (That’s a bit confusing because of the “32” in the regsvr32 name…)  To run the 32-bit regsvr32, do this:

cd \windows\syswow64
regsvr32 c:\filename.dll

(Note the stupidity of it all — the default regsvr32 is 64-bit and resides in the \windows\system32 directory.  Note the “32” in system32 and the “32” in regsvr32 — quite misleading.  However the 32-bit version of regsvr32 is found in the \windows\syswow64 directory.  Note the “64” in the directory name.  That’s also misleading.  Ughhh!)

More information about: regsvr32 or ActiveX object creation errors.

ActiveX on 64-bit OS; Which to use: 32-bit DLL or 64-bit DLL?

Question:

Help clarify something for me please. I develop in a 32bit environment, but
deploy to windows 2003/2008 64bit servers. Do I install the 64bit or the
32bit ActiveX on the servers?

Answer:

In Visual Studio C/C++ applications, you may target either win32 or x64. If your application targets win32, you should register (using regsvr32) and use the 32-bit Chilkat ActiveX DLL for both win32 and x64 systems. If your application targets x64, then you must register and use the x64 Chilkat ActiveX DLL and it may only run on 64-bit systems.

ClickOnce w/ x64 DLL’s

I recently discovered this crucial bit of information:

I compile my project for x86 systems (vs Any CPU or x64). Just wanted you to be aware of this. Your last email stated “You must deploy the x64 ChilkatDotNet2.dll to x64 systems” which is not correct.  This is an important consideration for “Click Once” deployments which do not have built-in conditional installations as do MSI installations. So by compiling for x86, “Click Once” deployments need only distribute the 32 bit version of Chilkat for both 32 and 64 bit systems.

My understanding has been refined to this:  It is possible to run either x86 or x64 EXE’s on the x64 architecture, however, DLL’s loaded by the EXE must match the architecture of the EXE (x86 or x64).  My guess is that an EXE created in a managed .NET application compiled to “Any CPU” would be required to load a DLL matching the processor architecture.

The Windows Registry can also be an issue.  This post describes how the registry on x64 Windows is divided into 32-bit and 64-bit keys.  If your EXE is loading an ActiveX DLL (not a .NET assembly) then an x86 EXE would be reading the x86 keys, but if the ActiveX registry information is in the x64 keys, you’ll get an error when trying to create the object — probably a “class not registered” type of error.

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.

Download for Vista x64 (64-bit Microsoft Vista)

Question:
I get an error when trying to load ChilkatDotNet2.dll on Vista x64:

An attempt was made to load a program with an incorrect format.

Does Chilkat have an x64-compatible .NET assembly?

Answer:
Yes, download the x64-compatible DLL from this URL:
x64 compatible ChilkatDotNet2.dll

Make sure you deploy the x64 DLL to the 64-bit Vista system. You may develop your application on a 32-bit system using the 32-bit ChilkatDotNet2.dll, just make sure you’re deploying the same version of the x64 ChilkatDotNet2.dll. The .NET runtime will not allow you to reference one version and use another at runtime.