New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BadImageFormatException when PlatformTarget architecture is different than current SDK #7532

Open
adamsitnik opened this Issue Aug 26, 2017 · 14 comments

Comments

Projects
None yet
7 participants
@adamsitnik
Member

adamsitnik commented Aug 26, 2017

Steps to reproduce

  1. Install x86 and x64 .NET Core SDKs
  2. Create new dotnet console app (dotnet new console)
  3. Set the PlatformTarget in explicit way to architecture different than your current SDK
  4. dotnet run
using System;

namespace report
{
    class Program
    {
        static void Main(string[] args) => Console.WriteLine($"IntPtr.Size={IntPtr.Size}");
    }
}
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <PlatformTarget>x64</PlatformTarget>
  </PropertyGroup>
</Project>

Expected behavior

dotnetcli runs the program for given platform target

Actual behavior

Program crashes:

Unhandled Exception: System.BadImageFormatException: Could not load file or assembly 'C:\temp\report\bin\Debug\netcoreapp2.0\report.dll'. An attempt was made to load a program with an incorrect format.

Environment data

dotnet --info output:

.NET Command Line Tools (2.1.0-preview1-007074)

Product Information:
 Version:            2.1.0-preview1-007074
 Commit SHA-1 hash:  ee5c02de77

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.14393
 OS Platform: Windows
 RID:         win10-x86
 Base Path:   C:\Program Files (x86)\dotnet\sdk\2.1.0-preview1-007074\

Microsoft .NET Core Shared Framework Host

  Version  : 2.1.0-preview2-25615-02
  Build    : 2d818e87081bfe71f9a3f2cbba43cb279e79b265

Why do I need that

In BenchmarkDotNet we generate, build and run new project for every benchmark. We use dotnet cli to do that. I would like to allow our users to compare the performance of x64 vs x86 with single config. I can imagine that dotnet cli team is busy. Could you at least give me some workaround?

@nguerrera

This comment has been minimized.

Show comment
Hide comment
@nguerrera

nguerrera Aug 26, 2017

Member

I'll be writing something up soon.

Member

nguerrera commented Aug 26, 2017

I'll be writing something up soon.

@nguerrera nguerrera self-assigned this Aug 26, 2017

@nguerrera

This comment has been minimized.

Show comment
Hide comment
@nguerrera
Member

nguerrera commented Sep 9, 2017

@nguerrera

This comment has been minimized.

Show comment
Hide comment
@nguerrera

nguerrera Sep 19, 2017

Member

By default, VS (and dotnet run) will just use the dotnet.exe that comes first on your PATH to run the application. If that is the x64 version of dotnet.exe, then you will not be able to debug x86 apps, and vice versa.

However, you can override the default run command. I suggest the following approach:

  1. Install both the x86 and x64 .NET Core 2.0 SDKs from https://www.microsoft.com/net/download/core
  2. Put the following in a file named Directory.Build.targets that is somewhere above your project file (e.g. the root of the source repository). MSBuild will pick it up automatically for all projects.
<Project>
  <PropertyGroup 
      Condition="'$(OS)' == 'Windows_NT' and
                 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
                 '$(SelfContained)' != 'true'"
                  >
    <RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand>
    <RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand>
  </PropertyGroup>
</Project>

What this does is the following:

  • If I'm building a .NET Core application on Windows and it is not self-contained (does not carry its own copy of the .NET Core runtime), then:
    • If it targets x86, use dotnet from C:\Program Files(x86)\dotnet
    • If it targets x64, use dotnet from C:\Program Files\dotnet

I am leaving this open to track making this work automatically without having to customize the RunCommand.

Member

nguerrera commented Sep 19, 2017

By default, VS (and dotnet run) will just use the dotnet.exe that comes first on your PATH to run the application. If that is the x64 version of dotnet.exe, then you will not be able to debug x86 apps, and vice versa.

However, you can override the default run command. I suggest the following approach:

  1. Install both the x86 and x64 .NET Core 2.0 SDKs from https://www.microsoft.com/net/download/core
  2. Put the following in a file named Directory.Build.targets that is somewhere above your project file (e.g. the root of the source repository). MSBuild will pick it up automatically for all projects.
<Project>
  <PropertyGroup 
      Condition="'$(OS)' == 'Windows_NT' and
                 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
                 '$(SelfContained)' != 'true'"
                  >
    <RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand>
    <RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand>
  </PropertyGroup>
</Project>

What this does is the following:

  • If I'm building a .NET Core application on Windows and it is not self-contained (does not carry its own copy of the .NET Core runtime), then:
    • If it targets x86, use dotnet from C:\Program Files(x86)\dotnet
    • If it targets x64, use dotnet from C:\Program Files\dotnet

I am leaving this open to track making this work automatically without having to customize the RunCommand.

@livarcocc livarcocc added this to the 2.1.0 milestone Sep 26, 2017

@ms0713

This comment has been minimized.

Show comment
Hide comment
@ms0713

ms0713 Nov 9, 2017

Is this problem solved with .net core 2.1.0???????

ms0713 commented Nov 9, 2017

Is this problem solved with .net core 2.1.0???????

@nguerrera

This comment has been minimized.

Show comment
Hide comment
@nguerrera

nguerrera Nov 9, 2017

Member

@ms0713 Nothing has changed yet. Did you try the steps I outlined above?

Member

nguerrera commented Nov 9, 2017

@ms0713 Nothing has changed yet. Did you try the steps I outlined above?

@ms0713

This comment has been minimized.

Show comment
Hide comment
@ms0713

ms0713 Nov 10, 2017

@nguerrera I m not able to find Directory.Build.targets file in my system. Have you tried any other solution?
In my case, my application is x64 and my VS is x86 so by default it takes x86 dotnet.exe to run my x64 bit app. Is there any other way to say VS that forcefully use this dotnet.exe?

ms0713 commented Nov 10, 2017

@nguerrera I m not able to find Directory.Build.targets file in my system. Have you tried any other solution?
In my case, my application is x64 and my VS is x86 so by default it takes x86 dotnet.exe to run my x64 bit app. Is there any other way to say VS that forcefully use this dotnet.exe?

@nguerrera

This comment has been minimized.

Show comment
Hide comment
@nguerrera

nguerrera Nov 10, 2017

Member

@ms0713 You can create a file named Directory.Build.targets in your project directory or any directory above it and MSBuild will pick it up. For example, put it at the root of the repository to affect all projects in the repository.

Member

nguerrera commented Nov 10, 2017

@ms0713 You can create a file named Directory.Build.targets in your project directory or any directory above it and MSBuild will pick it up. For example, put it at the root of the repository to affect all projects in the repository.

@ms0713

This comment has been minimized.

Show comment
Hide comment
@ms0713

ms0713 Nov 14, 2017

@nguerrera My OS is Windows Server 2012 R2, and I m using .Net Core 2.0 then what values i need to provide in $(OS) and $(TargetFrameworkIdentifier) ?

Also somebody suggested to change value in

ControlPanel->Advanced System Settings-> EnvironmentVariables -> Path
this also didnt worked. I provided here x64 bit dotnet.exe path C:\Program Files\dotnet.

Currently I used following values but it didnt worked.

<Project>
  <PropertyGroup 
      Condition="'$(OS)' == 'Windows Server 2012 R2' and
                 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
                 '$(SelfContained)' != 'true'"
                  >
    <RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand> <!-- Can I provide hard coded path for dotnet.exe here?  -->
    <RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand>
  </PropertyGroup>
</Project>

Which value is proper $(MSBuildProgramFiles32)\dotnet\dotnet or $(MSBuildProgramFiles32)\dotnet\dotnet.exe or $(MSBuildProgramFiles32)\dotnet?

ms0713 commented Nov 14, 2017

@nguerrera My OS is Windows Server 2012 R2, and I m using .Net Core 2.0 then what values i need to provide in $(OS) and $(TargetFrameworkIdentifier) ?

Also somebody suggested to change value in

ControlPanel->Advanced System Settings-> EnvironmentVariables -> Path
this also didnt worked. I provided here x64 bit dotnet.exe path C:\Program Files\dotnet.

Currently I used following values but it didnt worked.

<Project>
  <PropertyGroup 
      Condition="'$(OS)' == 'Windows Server 2012 R2' and
                 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
                 '$(SelfContained)' != 'true'"
                  >
    <RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand> <!-- Can I provide hard coded path for dotnet.exe here?  -->
    <RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand>
  </PropertyGroup>
</Project>

Which value is proper $(MSBuildProgramFiles32)\dotnet\dotnet or $(MSBuildProgramFiles32)\dotnet\dotnet.exe or $(MSBuildProgramFiles32)\dotnet?

@nguerrera

This comment has been minimized.

Show comment
Hide comment
@nguerrera

nguerrera Nov 14, 2017

Member

$(OS) will be Windows_NT on any Windows variant. Paste the file exactly as above.

Member

nguerrera commented Nov 14, 2017

$(OS) will be Windows_NT on any Windows variant. Paste the file exactly as above.

@ms0713

This comment has been minimized.

Show comment
Hide comment
@ms0713

ms0713 commented Nov 15, 2017

@nguerrera Thanks!!!

@ms0713

This comment has been minimized.

Show comment
Hide comment
@ms0713

ms0713 Nov 17, 2017

@nguerrera Now my application runs properly in Windows OS. But I m having problem running it on RHEL7.
When I run following command, it gives no error and command prompt comes back without doing anything. Also it gives no error or nothing.
$ dotnet AppName.dll 1
1 is command line argument.

My application uses SQL connection, Reflection, Third Party dlls( developed in c++), socket connection etc.

I also tried running a demo application with command line arguments, SQL connection. It works fine in RHEL7.
My application dll has version like 1.2.3.4.
While Publishing my code, it gives target runtime as Portable. But another sample with target runtime as Portable wotks fine in RHEL7.

What could be the problem? If you have any idea regarding this please share.

ms0713 commented Nov 17, 2017

@nguerrera Now my application runs properly in Windows OS. But I m having problem running it on RHEL7.
When I run following command, it gives no error and command prompt comes back without doing anything. Also it gives no error or nothing.
$ dotnet AppName.dll 1
1 is command line argument.

My application uses SQL connection, Reflection, Third Party dlls( developed in c++), socket connection etc.

I also tried running a demo application with command line arguments, SQL connection. It works fine in RHEL7.
My application dll has version like 1.2.3.4.
While Publishing my code, it gives target runtime as Portable. But another sample with target runtime as Portable wotks fine in RHEL7.

What could be the problem? If you have any idea regarding this please share.

@tang5188

This comment has been minimized.

Show comment
Hide comment
@tang5188

tang5188 commented Apr 28, 2018

thx

@joseclament

This comment has been minimized.

Show comment
Hide comment
@joseclament

joseclament Jun 7, 2018

I have a web job built on netcoreapp2.1 console application, targeting the win10-x64 and getting the "Unhandled Exception: System.BadImageFormatException: Could not load file or assembly exception".
I haven't had any issue with locally. Deployed using the visual studio directly to the app service. Any thoughts?

joseclament commented Jun 7, 2018

I have a web job built on netcoreapp2.1 console application, targeting the win10-x64 and getting the "Unhandled Exception: System.BadImageFormatException: Could not load file or assembly exception".
I haven't had any issue with locally. Deployed using the visual studio directly to the app service. Any thoughts?

@The-MAZZTer

This comment has been minimized.

Show comment
Hide comment
@The-MAZZTer

The-MAZZTer Sep 11, 2018

  1. Install both the x86 and x64 .NET Core 2.0 SDKs from https://www.microsoft.com/net/download/core

I only needed to install the x86 runtime after having the x64 SDK, FWIW.

I would suggest considering putting the x86 runtime in future Windows x64 SDK installers which have this bug fixed, This would make everything "just work".

However most people might not ever use it so it may be sufficient to have an error dialog prompting the user to download the x86 runtime if they try to debug an x86 dotnet application.

Also this Directory.Build.targets I found in one of the duplicate bugs works great for me. It doesn't seem to have made it to this main bug so here it is for convenience:

<Project>
	<PropertyGroup 
			Condition="'$(OS)' == 'Windows_NT' and
								 '$(PlatformTarget)' == 'x86' and
								 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
								 '$(SelfContained)' != 'true'"
									>
		<RunCommand>$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand>
	</PropertyGroup>

	<PropertyGroup
		Condition="'$(OS)' == 'Windows_NT' and
								 '$(PlatformTarget)' == 'x64' and
								 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
								 '$(SelfContained)' != 'true'"
									>
		<RunCommand>$(ProgramW6432)\dotnet\dotnet</RunCommand>
	</PropertyGroup>
</Project>

The-MAZZTer commented Sep 11, 2018

  1. Install both the x86 and x64 .NET Core 2.0 SDKs from https://www.microsoft.com/net/download/core

I only needed to install the x86 runtime after having the x64 SDK, FWIW.

I would suggest considering putting the x86 runtime in future Windows x64 SDK installers which have this bug fixed, This would make everything "just work".

However most people might not ever use it so it may be sufficient to have an error dialog prompting the user to download the x86 runtime if they try to debug an x86 dotnet application.

Also this Directory.Build.targets I found in one of the duplicate bugs works great for me. It doesn't seem to have made it to this main bug so here it is for convenience:

<Project>
	<PropertyGroup 
			Condition="'$(OS)' == 'Windows_NT' and
								 '$(PlatformTarget)' == 'x86' and
								 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
								 '$(SelfContained)' != 'true'"
									>
		<RunCommand>$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand>
	</PropertyGroup>

	<PropertyGroup
		Condition="'$(OS)' == 'Windows_NT' and
								 '$(PlatformTarget)' == 'x64' and
								 '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
								 '$(SelfContained)' != 'true'"
									>
		<RunCommand>$(ProgramW6432)\dotnet\dotnet</RunCommand>
	</PropertyGroup>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment