Skip to content
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 ASP.NET 4.6.1 AnyCPU setting #513

Closed
neodynamic opened this issue May 9, 2018 · 11 comments
Closed

BadImageFormatException ASP.NET 4.6.1 AnyCPU setting #513

neodynamic opened this issue May 9, 2018 · 11 comments

Comments

@neodynamic
Copy link

Description

Got BadImageFormatException at runtime when referencing SkiaSharp 1.60 nuget package in an ASP.NET 4.6.1 (MVC or WebForms) project with AnyCPU setting.

It works fine if ASP.NET Core project is involved so issue seems to happen with legacy ASP.NET projects

Code

Expected Behavior

Actual Behavior

Basic Information

  • Version with issue: 1.60
  • Last known good version:
  • IDE: VS 2017
  • Platform Target Frameworks: 4.6.1
    • Android:
    • iOS:
    • Linux:
    • macOS:
    • Tizen:
    • tvOS:
    • UWP:
    • watchOS:
    • Windows Classic:
  • Target Devices:

Screenshots

Reproduction Link

@mattleibow
Copy link
Contributor

Ah, this. This is hard to get right due to the way things are now. Basically, when you build AnyCPU, there is no reliable way to determine which platform you will be running on, so it copies both.

For example, I build on a x64 machine, but I may deploy to a x86 server somewhere. This causes an issue since the build doesn't know this - most probably it copied the native files for the DEV machine.

However, all is not lost, in the output folder, there will be 2 folders "x86" and "x64". In these folders, there will be the native files that each arch uses. You can just copy the native files out into the main output directory (either manually or as part of the project build).

One limitation of the current SkiaSharp is to P/Invoke directly, so there is no easy way within the library to load the correct one out of the two folders - this happens at build time. But, it is just a copy and should be fine as part of the deploy.

Another thing to check if you are building on x64, but it still fails is that there is a MSBuild element: <Prefer32Bit> that marks the .NET assemblies as x86 even on x64. This sometimes throws the loading out.

@mattleibow
Copy link
Contributor

What you can do is let me know what your setup is. Is this happening on the DEV box or the SERVER box? What are the architectures of both? What is the architecture of the native file? (I am sure there is a clever way to check this, but I just look at the file size - for libSkiaSharp, the x64 file is larger that the x86 file)

If you share this info, I may be able to help a bit more.

@neodynamic
Copy link
Author

neodynamic commented May 10, 2018

Thanks Matt for your response. The issue happens with ASP.NET MVC or WebForms targeting .NET 4.6.1+ with AnyCPU in dev machines (x64 arch) using VS 2017. It happens that SkiaSharp.targets is "deploying" x64 native lib in the BIN folder of the WebApp when AnyCPU is active. You have this logic in that targets file:

<!-- handle Any CPU, considering Prefer32Bit -->
        <PreferredNativeSkiaSharp Condition=" '$(PreferredNativeSkiaSharp)' == '' and '$(Prefer32Bit)' == 'False' ">x64</PreferredNativeSkiaSharp>  
        <PreferredNativeSkiaSharp Condition=" '$(PreferredNativeSkiaSharp)' == '' and '$(Prefer32Bit)' == 'True' ">x86</PreferredNativeSkiaSharp> 

And the first one of those conditions is taken place because "Prefer 32-bit" is grayed out because it seems to be a setting for .NET 4.5 only and for Desktop EXE Apps only (meaning the developer cannot Enable or Disable it) which will be always false.

So x64 libSkiaSharp.dll is deployed to BIN folder and failing at runtime with BadImageFormatException. Note that by default, IIS Express runs at 32bit so we think that you should give priority to x86 libSkiaSharp.dll and maybe not considering "Prefer 32-bit" option as it seems to be something available for .NET 4.5 exe projects only

@mattleibow
Copy link
Contributor

OK, I see what is happening, and this is quite easy to fix. Just add this element to the .csproj:

<PreferredNativeSkiaSharp>x86</PreferredNativeSkiaSharp>

This tells the targets file to copy the x86 version of the .dll - ignoring any magical detection (which it is getting wrong). You can also use cusom logic in your own .csproj to more accurately control this value.

I know this is a pain point with classic apps and Windows/Linux, but I hope to improve this sometime in the future.

@danroot
Copy link

danroot commented Jun 22, 2018

FYI, I had a similar issue publishing an ASP.NET Core app to Azure App Service. App Service was x86, so the app would work on dev machine but not after being published. This was my fix:

<ShouldIncludeNativeSkiaSharp>True</ShouldIncludeNativeSkiaSharp> <PreferredNativeSkiaSharp>x86</PreferredNativeSkiaSharp>

@mattleibow
Copy link
Contributor

I am going to close this issue as it appears to have been resolved.

If you want to avoid setting .csproj properties for development and servers, you can also use the msbuild property when creating/building on CI: /p:PreferredNativeSkiaSharp=x86.

@peterdebruijn
Copy link

I have the same issue. Where should I put x86 in the .csproj? Just adding it to the root causes my project to be invalid.

@mattleibow
Copy link
Contributor

You need to add it into the first <PropertyGroup> element.

@peterdebruijn
Copy link

Did not solve the issue for me...

@sbosell
Copy link

sbosell commented Jan 17, 2019

This issue wasn't resolved for me either by adding the two new properties. Core 2.0 app deploying to windows.

@peterdebruijn
Copy link

I have a c# ASP.Net application deploying to IIS in Azure

@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants