Error: ArcGIS Engine Controls fail to build using Visual Studio 2010 on a 64-bit OS
When building ArcGIS Engine Controls-based applications on a supported 64-bit Operating System (OS) targeting the Microsoft .NET 3.5 framework in Visual Studio 2010, the following error may occur:
"Could not load file or assembly 'file:///C:/Program Files (x86)/ArcGIS/DeveloperKit10.0/DotNet/ESRI.ArcGIS.3DAnalyst.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.
Line 162, position 5. C:\temp\Projects\MyArcGISControlApp\Form1.resx"
The error message may differ from the above error message depending on how the project is set up, what assemblies are referenced, and the install location of the ArcObjects .NET SDK on the machine being used.
Microsoft is aware of this problem and has provided the following knowledge base article as a solution to this problem:
Article ID: 2028833: "MSBuild 4.0 or Visual Studio 2010 may fail to compile a 32-bit application targeted for .Net Framework 3.5, 3.0 or 2.0 on x64 machine."
This issue occurs when a Visual Studio project contains a resource file (.resx) that is referencing a 32-bit (x86) assembly and is compiled against .NET 3.5 in Visual Studio 2010. Visual Studio uses an executable called 'ResGen.exe' during the build process. This executable is marked as MSIL (Any CPU) and runs as a 64-bit (x64) process on a 64-bit OS. Since the Esri Controls are 32-bit and marked as such, it attempts to load the 32-bit assembly and fails.
Solution or Workaround
The instructions provided in the Microsoft article (Article ID: 2028833) are sufficient to correct the problem. It involves changing the CorFlags section of the header of the executable to force it to run as a 32-bit application.
To understand what this is doing refer to the following scenario. If a developer creates .NET executable and sets the target platform to 'Any CPU', this essentially creates a header file in the executable that tells the Common Language Runtime (CLR) to load and run the executable in the same process space it was run in. When running the executable on a 32-bit machine, it would run as a 32-bit application; and on a 64-bit machine, it would run as a 64-bit application.
When creating an executable that references assemblies of a particular process's space, such as an ArcGIS Engine ArcObjects application, the process space should always be set to x86. Because the ArcObjects’ assemblies are only 32-bit, this forces the executable to always run as a 32-bit process regardless of the target machine and allows it to load the assemblies that are only 32-bit.
The workaround uses CorFlags.exe to change the header file of ResGen.exe so that it runs as a 32-bit application and allows it to correctly load the Esri 32-bit assemblies.
The steps detailed in the Microsoft article (Article ID: 2028833) can be automated within the project itself. For this to work correctly Visual Studio must and should be run as Administrator.
The following solution adds a custom build step to the Visual Studio project that temporarily changes the CorFlags section of the 'Resgen.exe' header file, so that the application compiles and then changes it back when finished.
The following instructions will make changes to essential Microsoft Visual Studio files and may potentially contain a security risk. Continue at your own risk!
These instructions are an adaptation of a solution provided by Microsoft. Esri is not responsible for any damage that this may cause to your Visual Studio install. It is recommended that you back up the <install location>\Microsoft SDKs\Windows\v7.0A\bin\ResGen.exe before proceeding.
- In Visual Studio 2010 right-click on the project and select 'Unload Project'.
- Right-click the project again and select 'Edit <project name>'. The XML for the project file can be edited from this location.
- Add the following XML anywhere in the project. Preferably at the end, just above the closing '</Project>' tag, where it is easy to find.
Workaround for VS2010 .NET 3.5 application referencing x86 assembly in resx file on 64-bit OS
<ForceResGen32Bit Condition="'$(MSBuildToolsVersion)'=='4.0' And '$(PROCESSOR_ARCHITEW6432)'!='' And '$(TargetingClr2Framework)'=='true' And '$(PlatformTarget)'=='x86'">true</ForceResGen32Bit>
<Target Name="BeforeResGen" Condition="'$(ForceResGen32Bit)' == 'true'">
<!-- Copy resgen.exe to intermediate working directory for UAC settings -->
<!-- corflags.exe resgen.exe /32BIT+ /Force-->
Command=""$(TargetFrameworkSDKToolsDirectory)corflags.exe" ResGen.exe /32BIT+ /Force" />
<!-- GenerateResource Task parameters
Using the non-64bit Tracker.exe and indicate resgen.exe has been forced to x86 -->
<Target Name="AfterResGen" Condition="'$(ForceResGen32Bit)' == 'true'">
<RemoveDir Directories="$(ResGenSdkToolsPath)" Condition="Exists('$(ResGenSdkToolsPath)')" />
- Right-click the project and select 'Reload Project'.
- Build the project.