![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
|
Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
br> br> |
| |||||||
![]() |
| | Thread Tools | Display Modes |
| | #1 (permalink) |
| Guest | Using WPF from PowerShell... I have seen all kind of examples where Windows Forms is used from PowerShell. Looked like fun so I tried to do the same with Windows Presentatio Foundation (WPF). My code: function LoadAssembly([string]$assembly) { $assemblyInfo = [System.Reflection.Assembly]::LoadWithPartialName($assembly) if($assemblyInfo -eq $null) { "unable to load assembly $assembly!" exit -1 } } LoadAssembly "PresentationCore" LoadAssembly "PresentationFramework" $form = new-object System.Windows.Window $form.Title = "hello" $form.Show The assemblies are found, but on construction of the System.Windows.Window object the constructor throws an exception: New-Object : Exception calling ".ctor" with "0" argument(s): "The calling thread must be STA, because many UI components require this." Is it possible to get PowerShell in STA moed, or do I need to create a CmdLet where a new thread is started in STA. I have seen code like this in CmsLets to solve this problem: protected override void BeginProcessing() { Thread queryThread = new Thread(ExecuteQuery); queryThread.SetApartmentState(ApartmentState.STA); queryThread.Start(); queryThread.Join(); } |
My System Specs![]() |
| | #2 (permalink) |
| Guest | Re: Using WPF from PowerShell... I've been waiting for someone to ask this :-) The problem is that the current PowerShell host defaults to using MTA threads and there's no way to change it. I don't even think you can work around this using a cmdlet in any useful way because you'd have to create an new STA thread to show the UI but there's no way to bind PowerShell actions to the controls. So you have to write a new host. This actually turns out not to be that difficult. Here's a simple winexe host that can run scripts that use XAML. Compile this file into an exe "stahost.exe" and then you can run scripts that use XAML by doing: ../stahost myxamlscript.ps1 This host takes advantage of the DefaultRunspace property and the fact that you can retrieve the $ExecutionContext from the runtime to build and execute scriptblocks on the host STA thread. (As always, this code is provided "AS IS" with no warranties.) The host code along with an example script that uses XAML are attached. (The XAML example is the calculator example that is distrubuted with the WPF SDK hacked up to be a PS script. -bruce --------------------------------------cut here----------------------------------- /* # PowerShell commands to compile this file $SMA = "$env:windir\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" csc /target:winexe /debug /r:$SMA stahost.cs */ using System; using System.Collections.ObjectModel; using System.Text; using System.IO; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Windows.Forms; class PowerShell { [STAThread] public static void Main(string[] args) { if (args.Length != 1) { MessageBox.Show("stahost: you must specify a script to run."); Environment.Exit(2); } try { string script = File.ReadAllText(args[0]); Runspace rs = RunspaceFactory.CreateRunspace(); // Must set the default runspace Runspace.DefaultRunspace = rs; rs.Open(); EngineIntrinsics engine = rs.SessionStateProxy .GetVariable("ExecutionContext") as EngineIntrinsics; // Now run the scriptblock on the Main (STA) thread // instead of the engine thread // which is MTA ScriptBlock sb = engine.InvokeCommand.NewScriptBlock(script); sb.Invoke(args); } catch (Exception e) { string position = "<script location unknown"; RuntimeException re = e as RuntimeException; if (re != null) { position = re.ErrorRecord.InvocationInfo.PositionMessage; } MessageBox.Show( String.Format( "stahost: error running script {0}\n{1}\n{2}\n{3}", args[0], e.Message, position, e)); } } } --------------------------------------cut here----------------------------------- -- Bruce Payette [MSFT] Windows PowerShell Technical Lead Microsoft Corporation This posting is provided "AS IS" with no warranties, and confers no rights. "Serge van den Oever [Macaw]" <SergevandenOeverMacaw@discussions.microsoft.com> wrote in message news:3CC9C966-4ADB-4337-9EF1-7F4281132B8D@microsoft.com... >I have seen all kind of examples where Windows Forms is used from >PowerShell. > Looked like fun so I tried to do the same with Windows Presentatio > Foundation > (WPF). > > My code: > > function LoadAssembly([string]$assembly) > { > $assemblyInfo = > [System.Reflection.Assembly]::LoadWithPartialName($assembly) > if($assemblyInfo -eq $null) > { > "unable to load assembly $assembly!" > exit -1 > } > } > > LoadAssembly "PresentationCore" > LoadAssembly "PresentationFramework" > $form = new-object System.Windows.Window > $form.Title = "hello" > $form.Show > > The assemblies are found, but on construction of the System.Windows.Window > object the constructor throws an exception: > > New-Object : Exception calling ".ctor" with "0" argument(s): "The calling > thread must be STA, because many UI components require this." > > Is it possible to get PowerShell in STA moed, or do I need to create a > CmdLet where a new thread is started in STA. > > I have seen code like this in CmsLets to solve this problem: > > protected override void BeginProcessing() > { > Thread queryThread = new Thread(ExecuteQuery); > queryThread.SetApartmentState(ApartmentState.STA); > queryThread.Start(); > queryThread.Join(); > } |
My System Specs![]() |
| | #3 (permalink) |
| Guest | Re: Using WPF from PowerShell... Hi Bruce, Thanks for following up on this one! It is an interesting possibility if we could levarage WPF within our powershell scripts! I tried out your application, but did not get it working. It doesn't seem to execute any script. I first tried my WPF script, didn't work. Script with just Write-Host "hello world" does not work, migght be that output pipes ar enot connected or something. Script with New-Item c:\test.txt does not work. So seems that scripts don't work at all... Any ideas? Serge "Bruce Payette [MSFT]" wrote: > I've been waiting for someone to ask this :-) The problem is that the > current PowerShell host defaults to using MTA threads and there's no way to > change it. I don't even think you can work around this using a cmdlet in any > useful way because you'd have to create an new STA thread to show the UI but > there's no way to bind PowerShell actions to the controls. > > So you have to write a new host. This actually turns out not to be that > difficult. Here's a simple winexe host that can run scripts that use XAML. > Compile this file into an exe "stahost.exe" and then you can run scripts > that use XAML by doing: > > ../stahost myxamlscript.ps1 > > This host takes advantage of the DefaultRunspace property and the fact that > you can retrieve the $ExecutionContext from the runtime to build and > execute scriptblocks on the host STA thread. (As always, this code is > provided "AS IS" with no warranties.) The host code along with an example > script that uses XAML are attached. (The XAML example is the calculator > example that is distrubuted with the WPF SDK hacked up to be a PS script. > > -bruce > > > --------------------------------------cut > here----------------------------------- > /* > > # PowerShell commands to compile this file > $SMA = > "$env:windir\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" > csc /target:winexe /debug /r:$SMA stahost.cs > > */ > using System; > using System.Collections.ObjectModel; > using System.Text; > using System.IO; > using System.Management.Automation; > using System.Management.Automation.Runspaces; > using System.Windows.Forms; > > class PowerShell > { > [STAThread] > public static void Main(string[] args) > { > if (args.Length != 1) > { > MessageBox.Show("stahost: you must specify a script to run."); > Environment.Exit(2); > } > > try { > string script = File.ReadAllText(args[0]); > > Runspace rs = RunspaceFactory.CreateRunspace(); > > // Must set the default runspace > Runspace.DefaultRunspace = rs; > rs.Open(); > EngineIntrinsics engine = rs.SessionStateProxy > .GetVariable("ExecutionContext") as EngineIntrinsics; > > // Now run the scriptblock on the Main (STA) thread > // instead of the engine thread > // which is MTA > ScriptBlock sb = engine.InvokeCommand.NewScriptBlock(script); > sb.Invoke(args); > } > catch (Exception e) > { > string position = "<script location unknown"; > RuntimeException re = e as RuntimeException; > if (re != null) > { > position = re.ErrorRecord.InvocationInfo.PositionMessage; > } > MessageBox.Show( > String.Format( > "stahost: error running script {0}\n{1}\n{2}\n{3}", > args[0], e.Message, position, e)); > } > } > } > > --------------------------------------cut > here----------------------------------- > > -- > Bruce Payette [MSFT] > Windows PowerShell Technical Lead > Microsoft Corporation > This posting is provided "AS IS" with no warranties, and confers no rights. > > > > "Serge van den Oever [Macaw]" > <SergevandenOeverMacaw@discussions.microsoft.com> wrote in message > news:3CC9C966-4ADB-4337-9EF1-7F4281132B8D@microsoft.com... > >I have seen all kind of examples where Windows Forms is used from > >PowerShell. > > Looked like fun so I tried to do the same with Windows Presentatio > > Foundation > > (WPF). > > > > My code: > > > > function LoadAssembly([string]$assembly) > > { > > $assemblyInfo = > > [System.Reflection.Assembly]::LoadWithPartialName($assembly) > > if($assemblyInfo -eq $null) > > { > > "unable to load assembly $assembly!" > > exit -1 > > } > > } > > > > LoadAssembly "PresentationCore" > > LoadAssembly "PresentationFramework" > > $form = new-object System.Windows.Window > > $form.Title = "hello" > > $form.Show > > > > The assemblies are found, but on construction of the System.Windows.Window > > object the constructor throws an exception: > > > > New-Object : Exception calling ".ctor" with "0" argument(s): "The calling > > thread must be STA, because many UI components require this." > > > > Is it possible to get PowerShell in STA moed, or do I need to create a > > CmdLet where a new thread is started in STA. > > > > I have seen code like this in CmsLets to solve this problem: > > > > protected override void BeginProcessing() > > { > > Thread queryThread = new Thread(ExecuteQuery); > > queryThread.SetApartmentState(ApartmentState.STA); > > queryThread.Start(); > > queryThread.Join(); > > } > > > |
My System Specs![]() |
![]() |
| Thread Tools | |
| Display Modes | |
| |
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Installing PowerShell dependent features on W2K8 with PowerShell CTP | Greg Wojan | PowerShell | 14 | 05-16-2008 08:15 AM |
| when run powershell script as windows service ,powershell fail | powershell fail on winodws 2008 | PowerShell | 6 | 01-15-2008 03:20 PM |
| Powershell Plus - Free for non commercial Use and Powershell Analyzer1.0 released | Karl Prosser[MVP] | PowerShell | 2 | 12-12-2007 12:43 PM |
| Automatic PowerShell Error Parsing in PowerShell Analyzer and PowerShellPlus | Karl Prosser[MVP] | PowerShell | 0 | 11-14-2007 02:32 AM |
| PowerShell Leaders Join Forces and offer a pre-release version of PowerShell for 50% off the retail value | klumsy@xtra.co.nz | PowerShell | 0 | 06-19-2007 02:42 PM |