ironmansoftware / psavalonia

Avalonia bindings for PowerShell
https://ironmansoftware.com
MIT License
59 stars 12 forks source link

ConvertTo-AvaloniaWindow throws exception on OSX 10.14.5 #1

Open johnmccrae opened 5 years ago

johnmccrae commented 5 years ago

Hi,

I loaded the module using install-module and followed the example code listed on Ironmansoftware.com

When I execute this line : $window = ConvertTo-AvaloniaWindow -Xaml $Xaml I get this error

`ConvertTo-AvaloniaWindow : The type initializer for 'PSAvalonia.AvaloniaBootstrapper' threw an exception. At line:1 char:1

johnmccrae commented 5 years ago

Here's more

Name Value


PSVersion 6.2.1 PSEdition Core GitCommitId 6.2.1 OS Darwin 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 Platform Unix PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0

vexx32 commented 5 years ago

After this exception occurs, can you call $error[0].Exception.GetBaseException() | select * and post the resulting messages?

johnmccrae commented 5 years ago

Sorry, should have thought of that already. Here you go:

PS /Users/jmccrae> $error[0].Exception.GetBaseException() | select *

Message : Call from invalid thread Data : {} InnerException : TargetSite : Void VerifyAccess() StackTrace : at Avalonia.Threading.Dispatcher.VerifyAccess() at Avalonia.Rendering.RenderLoop.Add(IRenderLoopTask i) at Avalonia.Application.RegisterServices() at Avalonia.Controls.AppBuilderBase1.Setup() at Avalonia.Controls.AppBuilderBase1.SetupWithoutStarting() at PSAvalonia.AvaloniaBootstrapper..cctor() in F:\ps-avalonia\src\AvaloniaBootrapper.cs:line 20 HelpLink : Source : Avalonia.Base HResult : -2146233079

johnmccrae commented 5 years ago

One more item - I tested this on PS Core 6.2.1 running on Ubuntu 16.04 and that code snippet above works fine

jzeiders commented 5 years ago

Getting the same issue on 7.0 preview. Anyone find a fix?

PSVersion 7.0.0-preview.2 PSEdition Core GitCommitId 7.0.0-preview.2 OS Darwin 17.7.0 Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-… Platform Unix PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0

TylerLeonhardt commented 5 years ago

This is an upstream issue - https://github.com/AvaloniaUI/Avalonia/issues/2800

ALIENQuake commented 5 years ago

@jzeiders With the recent release of https://github.com/powershell/GraphicalTools, can you share how you did overcome this issue? I have a PSAvalonia project which doesn't work on MacOS because of this bug. And I can't yet use GraphicalTools, to create custom window from custom XAML?

TylerLeonhardt commented 5 years ago

Basically, GraphicalTools uses a separate process that launches the GUI. This is really the only way it can be done.

The GraphicalTools PowerShell module starts up this other process and talks to it over stdio.

Here's the code for the other process: https://github.com/PowerShell/GraphicalTools/tree/master/src/OutGridView.Gui

ALIENQuake commented 5 years ago

@TylerLeonhardt Excuse me for bring this topic again but this looks like a very serious major obstacle when it comes to creating a Powershell Avalonia GUI application which works for MacOS.

Let's assume that I have very simple GUI app: a textbox window with two buttons: Ok and Chancel. Pressing "OK" will put some text into textbox. If I understand you correctly, for Windows and Linux, everything is fine, everything works pretty much the same as Forms/WPF - buttons with event handlers will execute their code on the current powershell process.

But when you are on MacOS, you can't create window from the same powershell process which was used to load ps1 because you are getting crash. So you need to create separate process for GUI. And you need to 'talk to it over stdio'. Does this separate process has any kind of limitation when if comes to how 'OK' button with event handler will work? The window is on different process, I'm pressing 'OK', event handler is executed on this separate process.The textbox should be filed, right?

TylerLeonhardt commented 5 years ago

Does this separate process has any kind of limitation when if comes to how 'OK' button with event handler will work?

You'll need to set up the event handler in the GUI process, and then in the handler send any data that needs to go back to the PowerShell module through stdio so that your module can process the data if it needs to and then send any result back to the GUI process to be rendered.

This extra architecture has showed up because we assumed that macOS had the same threading freedom as Windows... But that's not the case - macOS is very strict on this matter which forces us to use another process.

ALIENQuake commented 5 years ago

@TylerLeonhardt Right, but if I'm not using 'module' and all 'application' code will be pasted/ dot sourced by the GUI process?

TylerLeonhardt commented 5 years ago

Apologies, I'm not sure I understand the question.

ALIENQuake commented 5 years ago

@TylerLeonhardt Sorry, probably best to leave this for now, until it gest's attention from author.

@adamdriscoll Do you see any way to 'fix' this? Even if it would mean that the module would have to be rewrite or even be the included directly in the script witch is used to launch the 'PSAvalonia' extra code/cmdlets etc? Just anything to allow normal workflow.

adamdriscoll commented 5 years ago

@ALIENQuake Aside from doing what @TylerLeonhardt mentioned, I'm not sure how to accomplish this. It seems like it will be a lot of work to serialize data back and forth from event handlers and any objects will not be "live". So the event handlers won't work as you expect because all the actual live instances are living in a separate process.

So it's possible to make it kinda feel like it works like WPF but it will have some caveats.

ALIENQuake commented 5 years ago

@adamdriscoll It sounds like a lost case, that's terrible 😢 It seems that there is no way to have cross-platform GUI which can be handled from the Powershell itself (it can be from c#) because any kind of similar framework will face the same issue?

Desperate times needs desperate actions: How about a possibility to include all of the PSAvalonia code directly inside Powershell code, compile it as custom executable and execute GUI code/commands directly from such custom pwsh executable? Assuming that it would be ugliest hack ever, does it will overcome this issue?

TylerLeonhardt commented 5 years ago

Including it in PowerShell won't change anything, unfortunately.

The problem is because PowerShell runs PowerShell script on a background thread, rather than the main thread. MacOS doesnt allow gui code to be run on background threads.

The only way to possibly fix this is to change PowerShell to run scripts on the main thread but we tried it and PowerShell did not handle the change well. It's not impossible, but we don't have the resources or time to focus on the change in PowerShell.

TylerLeonhardt commented 5 years ago

Also we'd basically double the size of PowerShell if we included Avalonia as a dependency. Which is sadly a non-starter

ALIENQuake commented 5 years ago

@TylerLeonhardt Thanks for detailed explanation, even if it's heartbreaking 😢 While using c# makes things more time consuming for me, it will do the job. Thanks again.

ALIENQuake commented 4 years ago

The only way to possibly fix this is to change PowerShell to run scripts on the main thread but we tried it and PowerShell did not handle the change well. It's not impossible, but we don't have the resources or time to focus on the change in PowerShell.

@TylerLeonhardt Excuse me for bringing this topic again, I waited until the PS 7 release, hopefully, the team have some breathing space now.

I have an idea of how this issue can be handled, it all depends on what 'did not handle the change well` means. How serious the problems were? Crashes? Performance? Modules don't work?

How about creating a special release type of the PS itself: just like PowerShell-7.0.0-win-fxdependent and PowerShell-7.0.0-win-fxdependentWinDesktop, it would be PowerShell-7.0.0-os-single-thread. It would contain minimal code changes that will change PS to be single-thread.

Let's consider only one possible scenario where such PS-SingleThread would be used: as a dependency and bundled with the application itself, just like the NuGet package. All other scenarios would be not supported. Basically, I only need core PS functionality, without any extra modules, etc.

Then, PSAvalonia can bundle this special version and the PS-based, cross-platform GUI application can be created. Thoughts?

TylerLeonhardt commented 4 years ago

I was hoping such a change could be done in

https://github.com/PowerShell/PowerShell/pull/10962#issuecomment-551910972

Which introduces a pwshw

But it would have to be a separate PR

ALIENQuake commented 4 years ago

@TylerLeonhardt Good to know. Is there any other issue where this topic is being tracked? Or some leftover PS-single-thread related code which someone could look at it, compile and do some experiments?

TylerLeonhardt commented 4 years ago

@ALIENQuake this was the code change in PowerShell itself... but the risk of doing that was unknown so we didn't take the change.

https://github.com/SteveL-MSFT/PowerShell/commit/41c3b0f3a41eb5d7897339cb22cad26c0a801c9f

ALIENQuake commented 4 years ago

@adamdriscoll @TylerLeonhardt Sucess! The above crash was due to the fact that I compile PS from the latest branch which happens to switch to .NET 5 moments ago. After compiling PS for NET Core 3.1 crash no longer occurs!

Look at this nice window: image

@adamdriscoll Could you update PSAvalonia to the latest version of Avalonia 0.9.4? Or create minimal documentation on how to do it so hopefully, I won't be too hard and I could send PR?

vexx32 commented 4 years ago

@ALIENQuake all you should need to do is update the dependency reference version in the csproj file and rebuild the project with dotnet publish. You'll probably need to do some manual copying of the built DLLs since I don't see a build script for this project in the repo.

ALIENQuake commented 4 years ago

@vexx32 I don't think it will be so easy, and if so, the module at PSGallery will still have old dll's. I guess I have to wait for Adam's feedback.

adamdriscoll commented 4 years ago

@ALIENQuake - I can update the proj to the latest version. I will also make a build script and publish an updated version to the gallery. All we need to do is just update to Avalonia 0.9.4?

ALIENQuake commented 4 years ago

@adamdriscoll I don't think so, since 0.8.x, Avalonia received some updates to the App initialization process. Please take look at the updated default sample: https://github.com/AvaloniaUI/Avalonia/blob/master/samples/ControlCatalog.Desktop/Program.cs#L25. I can test whatever you release if you currently have time for the maintenance update.

One question: have you thought about the way of converting the c#-part of the module into normal PowerShell code? I believe this could be beneficial for 'quick start' and for the bundling process.

ALIENQuake commented 3 years ago

@TylerLeonhardt @vexx32 @adamdriscoll

EDIT: Case 2 It's chicken-egg problem, Case 1 works.

Getting back to this, I was able to ( case 1 ):

and it basically works, without requiring to modify PowerShell code itself.

Case 2 would be to change ThreadOptions for the currently launched pwsh process which is used to launch scrpit.ps1

Things I've tried:

CreateRunspace(  [NamedPipeConnectionInfo]::new($PID), $host, [TypeTable]::LoadDefaultTypeFiles()) 

and

CreateOutOfProcessRunspace([TypeTable]::LoadDefaultTypeFiles(), [PowerShellProcessInstance]::new())

but none of those was successful.

Maybe I'm missing something? If not, can you confirm that it's impossible to change ThreadOptions property to UseCurrentThread for the currently launched pwsh process?