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

ConvertTo-AvaloniaWindow throws exception on OSX 10.14.5 #1

Open
johnmccrae opened this issue Jun 18, 2019 · 28 comments
Open

ConvertTo-AvaloniaWindow throws exception on OSX 10.14.5 #1

johnmccrae opened this issue Jun 18, 2019 · 28 comments

Comments

@johnmccrae
Copy link

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

  • ConvertTo-AvaloniaWindow -Xaml $Xaml
  • CategoryInfo : NotSpecified: (:) [ConvertTo-AvaloniaWindow], TypeInitializationException
  • FullyQualifiedErrorId : System.TypeInitializationException,PSAvalonia.ConvertToAvaloniaWindow`
@johnmccrae
Copy link
Author

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
Copy link

vexx32 commented Jun 18, 2019

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

@johnmccrae
Copy link
Author

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
Copy link
Author

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
Copy link

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
Copy link

This is an upstream issue - AvaloniaUI/Avalonia#2800

@ALIENQuake
Copy link

@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
Copy link

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
Copy link

ALIENQuake commented Aug 20, 2019

@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
Copy link

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
Copy link

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

@TylerLeonhardt
Copy link

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

@ALIENQuake
Copy link

ALIENQuake commented Aug 21, 2019

@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
Copy link
Member

@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
Copy link

@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
Copy link

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
Copy link

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

@ALIENQuake
Copy link

ALIENQuake commented Aug 22, 2019

@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
Copy link

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
Copy link

I was hoping such a change could be done in

PowerShell/PowerShell#10962 (comment)

Which introduces a pwshw

But it would have to be a separate PR

@ALIENQuake
Copy link

@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
Copy link

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

SteveL-MSFT/PowerShell@41c3b0f

@ALIENQuake
Copy link

ALIENQuake commented Mar 20, 2020

@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
Copy link

vexx32 commented Mar 20, 2020

@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
Copy link

@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
Copy link
Member

@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
Copy link

@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
Copy link

ALIENQuake commented Apr 10, 2021

@TylerLeonhardt @vexx32 @adamdriscoll

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

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

  • create c# app with PowerShell SDK
  • create runspace, change Runspace ThreadOptions property to UseCurrentThread
  • addScript from local file

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?

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

No branches or pull requests

6 participants