BepInEx icon indicating copy to clipboard operation
BepInEx copied to clipboard

Fix for .NET launcher not loading x64 compiled assemblies

Open dywersant opened this issue 4 years ago • 2 comments

What happened?

One of the files in this game is compiled as x64, raising BadImageFormatException in .NET launcher. Please change https://github.com/BepInEx/BepInEx/blob/4304b817dab28581d531c5fa7a48c87cf8c910b1/BepInEx.NetLauncher/BepInEx.NetLauncher.csproj#L15

to AnyCPU to fix this issue, or create targets for x86 and x64

Steps to reproduce

No response

BepInEx Distribution

Bleeding Edge from BepisBuilds

Log outputs

[Message: Preloader] BepInEx 6.0.0 - Stay Safe
[Info   :   BepInEx] System platform: Bits64, Windows
[Info   : Preloader] CLR runtime version: 4.0.30319.42000
[Message: Preloader] Preloader started
[Info   : Preloader] 0 patcher definition(s) loaded
[Debug  :AssemblyPatcher] Assembly loaded: Champs.dll
[Debug  :AssemblyPatcher] Assembly loaded: LitJSON.dll
[Debug  :AssemblyPatcher] Assembly loaded: MonoGame.Framework.dll
[Debug  :AssemblyPatcher] Assembly loaded: Okay.dll
[Debug  :AssemblyPatcher] Assembly loaded: RogueSharp.dll
[Debug  :AssemblyPatcher] Assembly loaded: Steamworks.NET.dll
[Debug  :AssemblyPatcher] Assembly loaded: BepInEx.NetLauncher.exe
[Debug  :AssemblyPatcher] Assembly loaded: Stay Safe.exe
[Info   : Preloader] 8 assemblies discovered
[Message:AssemblyPatcher] Executing 0 patch(es)
[Debug  : Preloader] Using entrypoint assembly from disk
[Message: Preloader] Preloader finished
[Message:   BepInEx] Chainloader initialized
[Info   :   BepInEx] 0 plugins to load
[Message:   BepInEx] Chainloader startup complete
[Fatal  : Preloader] Unhandled exception: System.Reflection.TargetInvocationException: Obiekt docelowy wywołania zgłosił wyjątek. ---> System.BadImageFormatException: Nie można załadować pliku lub zestawu 'Steamworks.NET, Version=14.0.0.0, Culture=neutral, PublicKeyToken=null' lub jednej z jego zależności. Próbowano załadować program w niepoprawnym formacie.
   w StaySafeRL.SSRL..ctor()
   w StaySafeRL.Program.Main(String[] _args)
   --- Koniec śladu stosu wyjątków wewnętrznych ---
   w System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   w System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   w System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   w System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   w BepInEx.NetLauncher.NetPreloader.Start(String[] args)

Environment

- OS: Win64
- BepInEx: 
- Game: Stay Safe

dywersant avatar Sep 09 '21 21:09 dywersant

This is a complex issue that can't be (properly) fixed by setting it to AnyCPU. There's a specific reason why it's working for you

A C# library being set to AnyCPU is straightforward because it will then load with the bitness of the host process. Setting a C# application to AnyCPU isn't as simple because the .NET runtime must decide if the application is running in x86 or x64.

How it determines that is by checking if you have the <Prefer32Bit> property set to true in the csproj file. If true, the process is started as x86, otherwise x64. That's why changing it directly to AnyCPU works in your case, because that flag is not set (to true) and Windows is launching the process as x64.

This doesn't work for games that need to be launched in x86 (for example, vanilla XNA games). Descendants of XNA such as FNA or MonoGame typically target x64.

On top of providing builds for x64 and x86 variants, we need to make builds for different .NET versions as the host process also determines which version of .NET the entire process uses (for example, using NetLauncher compiled for 4.5 will break Terraria as it's compiled against 4.0 Client for a very detailed reason I won't get into here). Otherwise patches for the game will need to be made to get around that

So this is TBA me figuring out how to get msbuild and our cake script to compile a project in multiple .net versions cleanly

bbepis avatar Sep 10 '21 07:09 bbepis

Yes, I have noticed this after posting this issue. Building for AnyCPU will not work for games built as x86, like Terraria. I understand that these targets are not that popular, so they wont be prioritized.

dywersant avatar Sep 10 '21 10:09 dywersant