fsprojects / Interstellar

Cross-platform desktop apps in F# using web tech - https://www.nuget.org/packages/Interstellar.Core/
https://fsprojects.github.io/Interstellar/
MIT License
43 stars 13 forks source link

WinForms example crashes in Release mode #10

Closed jwosty closed 3 years ago

jwosty commented 3 years ago

WinForms example works fine in Debug mode, but crashes in Release mode (regardless of running under .net core 3, .net framework, or .net 5):

System.IO.FileNotFoundException: 'Could not load file or assembly 'CefSharp.Core, Version=86.0.241.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138'. The system cannot find the file specified.'

In the past, this has indicated something going wrong with runtime CefSharp DLL resolver (see https://github.com/jwosty/Interstellar/blob/master/src/Interstellar.WindowsCommon.Chromium/Platform.fs#L36), but I'm not sure how this is happening only in release but not in debug. And only in WinForms, specifically. Wpf is all fine and I can't find any differences.

jwosty commented 3 years ago

I'm thinking of just deleting the WinForms package. Why would you want it anyway? I can't think of a valid use case, since this isn't a legacy library.

amaitland commented 3 years ago

In the past, this has indicated something going wrong with runtime CefSharp DLL resolver (see https://github.com/jwosty/Interstellar/blob/master/Interstellar.WindowsCommon.Chromium/Platform.fs#L36)

Link is broken, can you provide working link so I can have a look.

jwosty commented 3 years ago

@amaitland link repaired

jwosty commented 3 years ago

It's probably relevant that I'm using CefSharp in AnyCPU mode. The WinForms sample did work in the past if memory serves me correctly.

amaitland commented 3 years ago

Thanks. I'm restructuring the CefSharp Nuget packages in an attempt to simplify usage, including AnyCpu. Looking for real world test cases, make sure I haven't broken anything.

I'll take a look at the this while I'm at it. Full disclaimer I've never written f# before 😄

jwosty commented 3 years ago

Oh, interesting, how are you restructuring? Is there a more detailed topic somewhere else? I'm curious

No problem, I'm happy to provide whatever info you need! I appreciate the help a lot.

amaitland commented 3 years ago

Oh, interesting, how are you restructuring? Is there a more detailed topic somewhere else? I'm curious

Sure, see https://github.com/cefsharp/CefSharp/issues/3319

I'm hoping to improve some scenarios like this one. Moving the managed CLI/C++ code into an assembly that's not directly references so I can have more control over how it's loaded. This will be an interesting test actually.

I've not used Paket before, any references you think are worth reading? Specifically I need to add the https://www.myget.org/F/cefsharp/ feed and upgrade to the latest CI Build.

No problem, I'm happy to provide whatever info you need! I appreciate the help a lot.

So from my understanding here's what's happening in Release

Quick test and commit https://github.com/amaitland/Interstellar/commit/84d690aac280a09a80d57d2e679dd90436dfe00c should resolve the problem. You'll probably want to restructure it a little so it first with your style 😄

amaitland commented 3 years ago

Totally off topic and happy to open a seperate discussion, I was having a little bit of a look through the code, are you injecting javascript for the sole purpose of proxying window.interstellarBridge.postMessage to CefSharp.PostMessage?

https://github.com/jwosty/Interstellar/blob/ddf1a0151bb69125f5d4d83556ea521364788d84/src/Interstellar.Chromium/Browser.fs#L24

You should be able to customise the naming without having to jump through all those hoops. Fairly recently the option to configure the name of the object CefSharp injects into the browser was added (e.g. instead of CefSharp you can have it create the object as interstellarBridge

browser.JavascriptObjectRepository.Settings.JavascriptBindingApiGlobalObjectName = "interstellarBridge";

http://cefsharp.github.io/api/86.0.x/html/P_CefSharp_IJavascriptObjectRepository_Settings.htm http://cefsharp.github.io/api/86.0.x/html/P_CefSharp_JavascriptBinding_JavascriptBindingSettings_JavascriptBindingApiGlobalObjectName.htm

jwosty commented 3 years ago

Totally off topic and happy to open a seperate discussion, I was having a little bit of a look through the code, are you injecting javascript for the sole purpose of proxying window.interstellarBridge.postMessage to CefSharp.PostMessage?

https://github.com/jwosty/Interstellar/blob/ddf1a0151bb69125f5d4d83556ea521364788d84/src/Interstellar.Chromium/Browser.fs#L24

You should be able to customise the naming without having to jump through all those hoops. Fairly recently the option to configure the name of the object CefSharp injects into the browser was added (e.g. instead of CefSharp you can have it create the object as interstellarBridge

browser.JavascriptObjectRepository.Settings.JavascriptBindingApiGlobalObjectName = "interstellarBridge";

http://cefsharp.github.io/api/86.0.x/html/P_CefSharp_IJavascriptObjectRepository_Settings.htm http://cefsharp.github.io/api/86.0.x/html/P_CefSharp_JavascriptBinding_JavascriptBindingSettings_JavascriptBindingApiGlobalObjectName.htm

Separate issue would probably be good for that, but yeah I'd be happy to talk about it. Honestly I don't remember how those bits in particular work right now so I'll have to look into them again and get back to you. I really appreciate the feedback!

jwosty commented 3 years ago

Oh, interesting, how are you restructuring? Is there a more detailed topic somewhere else? I'm curious

Sure, see cefsharp/CefSharp#3319

I'm hoping to improve some scenarios like this one. Moving the managed CLI/C++ code into an assembly that's not directly references so I can have more control over how it's loaded. This will be an interesting test actually.

I've not used Paket before, any references you think are worth reading? Specifically I need to add the https://www.myget.org/F/cefsharp/ feed and upgrade to the latest CI Build.

No problem, I'm happy to provide whatever info you need! I appreciate the help a lot.

Assuming I properly understand the stuff in cefsharp/CefSharp#3319, I think Paket should work fine with most of this stuff. Paket's restore functionality is invoked automatically as part of dotnet restore; it has good tooling integration. Though it would be interesting to investigate. This other repo is self contained and references my lib (and therefore indirectly your lib), and therefore might be a good test case for you: https://github.com/jwosty/InterstellarFableHelloWorld/

Perhaps this will be useful: https://fsprojects.github.io/Paket/paket-and-dotnet-cli.html

So from my understanding here's what's happening in Release

* Compiler Inlines code where possible for performance reasons.

* Now the code is inline the `CLR` has to load the required dependencies including the `CefSharp.*.dll`

* Your code to hook Assembly Resolve never gets a chance to run now.

Quick test and commit amaitland@84d690a should resolve the problem. You'll probably want to restructure it a little so it first with your style 😄

Fix seems to work, thank you. I've adapted it into PR #14 by moving it into the library itself.