Knowledge Base - Technical Articles


Technical Article   Error:  ArcGIS Engine Controls fail to build using Visual Studio 2010 on a 64-bit OS

Article ID: 37879
Software:  ArcGIS Engine Developer Kit 10
Platforms:  Windows 2003Server, 2008Server, Win 7

Error Message

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

Cause

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.



  1. In Visual Studio 2010 right-click on the project and select 'Unload Project'.
  2. Right-click the project again and select 'Edit <project name>'. The XML for the project file can be edited from this location.
  3. 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
    http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/e5900710-9849-4d10-aa28-48b734d06bf2

    -->
    <PropertyGroup>
    <ForceResGen32Bit Condition="'$(MSBuildToolsVersion)'=='4.0' And '$(PROCESSOR_ARCHITEW6432)'!='' And '$(TargetingClr2Framework)'=='true' And '$(PlatformTarget)'=='x86'">true</ForceResGen32Bit>

    </PropertyGroup>
    <Target Name="BeforeResGen" Condition="'$(ForceResGen32Bit)' == 'true'">
    <PropertyGroup>
    <ResGenSdkToolsPath>$(IntermediateOutputPath)ResGenForced32Bit\</ResGenSdkToolsPath>
    </PropertyGroup>
    <!-- Copy resgen.exe to intermediate working directory for UAC settings -->
    <Copy SourceFiles="$(TargetFrameworkSDKToolsDirectory)ResGen.exe"
    DestinationFiles="$(ResGenSdkToolsPath)ResGen.exe" />

    <!-- corflags.exe resgen.exe /32BIT+ /Force-->
    <Exec WorkingDirectory="$(ResGenSdkToolsPath)"
    Command="&quot;$(TargetFrameworkSDKToolsDirectory)corflags.exe&quot; ResGen.exe /32BIT+ /Force" />

    <!-- GenerateResource Task parameters
    Using the non-64bit Tracker.exe and indicate resgen.exe has been forced to x86 -->
    <PropertyGroup>
    <ResGenTrackerSdkPath>$(SDK40ToolsPath)</ResGenTrackerSdkPath>
    <ResGenToolArchitecture>Managed32Bit</ResGenToolArchitecture>
    <CacheTargetFrameworkSDKToolsDirectory>$(TargetFrameworkSDKToolsDirectory)</CacheTargetFrameworkSDKToolsDirectory>
    <TargetFrameworkSDKToolsDirectory>$(ResGenSdkToolsPath)</TargetFrameworkSDKToolsDirectory>
    </PropertyGroup>
    </Target>
    <Target Name="AfterResGen" Condition="'$(ForceResGen32Bit)' == 'true'">
    <PropertyGroup>
    <TargetFrameworkSDKToolsDirectory>$(CacheTargetFrameworkSDKToolsDirectory)</TargetFrameworkSDKToolsDirectory>
    </PropertyGroup>

    <RemoveDir Directories="$(ResGenSdkToolsPath)" Condition="Exists('$(ResGenSdkToolsPath)')" />
    </Target>

  4. Right-click the project and select 'Reload Project'.
  5. Build the project.

Related Information


Created: 6/15/2010
Last Modified: 7/2/2010

Article Rating: (3)
If you would like to post a comment, please login

Comments

By eliprandi - 03/16/2012 8:02 AM

The article needs to be updated.

How about with 10.1? with the switch to MSIL as the target for what seemed to be all of ArcObjects, we have found that 4 DLLs are still targeting 32bits only (using corflags). Those are: ESRI.ArcGIS.ADF.Connection ESRI.ArcGIS.ADF.Connection.Local ESRI.ArcGIS.ADF ESRI.ArcGIS.ADF.Local Out of 87 DLLs in the DotNet folder for 10.1 Pre-Release, those are the only 4 that are not set to MSIL as the architecture. Considering that ESRI.ArcGIS.ADF.Local contains both BaseCommand and BaseTool from which ALL our commands and tools inherit, it's a bit of a hassle to force all our projects to be manually edited for that DLL alone. Regards,

Rating:

By Anonymous - 12/10/2010 3:32 PM

The article needs to be updated.

I would like to see ESRI Development SDKs support NET 4. The limitation to NET 3.5 is the problem.

Rating:

By Anonymous - 08/06/2010 10:25 AM

The article contains a dead link.

I followed the ESRI workaround version. The project will now build but it does not run or debug.

Rating: