Skip to content
This repository has been archived by the owner on Nov 7, 2022. It is now read-only.

Packaging - BadImageFormatException when running in 32 Bit mode #291

Closed
andrekoehler opened this issue Feb 5, 2018 · 6 comments
Closed
Labels

Comments

@andrekoehler
Copy link
Contributor

I get a

System.BadImageFormatException
HResult=0x8007000B
Message=An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
Source=Urho
StackTrace:
at Urho.Context.Context_Context()
at Urho.Context..ctor()
at Urho.Application..ctor(ApplicationOptions options)
at the first line of my code that uses Urho

This only occurs when running with the x86 build or the AnyCPU+Prefer32 build.

The reason for this lies in here:

<None Include="$(MSBuildThisFileDirectory)\..\..\native\Win64\mono-urho.dll">
<Link>mono-urho.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)\..\..\native\Win32\mono-urho.dll">
<Link>mono-urho_32bit.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

And the Platform Invoke code uses a compile time constant instead of deciding the name of the DLL at runtime:

internal static class Consts
{
#if DESKTOP
public const string NativeImport = "mono-urho";

It would be great, if the UrhoSharp wrapper could decide at runtime which architecture of the native DLL to load.

@andrekoehler
Copy link
Contributor Author

Here is a workaround for the case where you want to use UrhoSharp in a 32 bit only application:
Add the following lines in the project properties of your C# project under "Build Events" -> "Post-build event command line:"

DEL "$(TargetDir)mono-urho.dll"
RENAME "$(TargetDir)mono-urho_32bit.dll" "mono-urho.dll"

@migueldeicaza migueldeicaza changed the title BadImageFormatException when running in 32 Bit mode Packaging - BadImageFormatException when running in 32 Bit mode Feb 5, 2018
@migueldeicaza
Copy link
Contributor

This is generally a problem with .NET that has a very inflexible system for loading libraries.

There are some proposals to look into this:

https://github.com/dotnet/coreclr/issues/12707

So at this point, I would just wait for this to be fixed at the core.

@EgorBo
Copy link
Member

EgorBo commented Mar 1, 2018

Usually on Windows developers solve this problem by ugly MSBuild hacks like "post-build tasks" 🙁

@andrekoehler
Copy link
Contributor Author

You could also use a small hack like this one: https://stackoverflow.com/a/30646096/2955654

@EgorBo EgorBo closed this as completed in 30b9e6d Mar 1, 2018
@EgorBo
Copy link
Member

EgorBo commented Mar 1, 2018

@andrekoehler perfect, thanks, it will also allow to switch between OpenGL and DirectX easily via ApplicationOptions

@dotMorten
Copy link
Contributor

I have a much better way to handle this. The trick is to deploy both the x64 and x86 DLL in sub-folders, and make the two DLLs named the same. You then call SetDllDirectory based on the running architecture. You can see how I do that here:
https://github.com/dotMorten/IoTivityDotNet/blob/master/src/IotivityDotNet.Interop/Init.cs

Then in the nuget package you add a .targets file that xcopy deploys the correct one or both based on your anycpu/prefer32bit/x86/x64 build settings. You can see an example of my targets file here:
https://github.com/dotMorten/IoTivityDotNet/blob/master/src/IotivityDotNet.Interop/build/net452/dotMorten.IoTivity.Interop.targets

This approach allows users to create AnyCPU apps and run the same app on both x86 and x64 platforms.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants