Windows Vista Forums
Vista Forums Home Join Vista Forums Donate Vista Tutorials Tags

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.
Register at Vista forums...the world biggest Windows Vista resource Join Vista Forums Now

Go Back   Vista Forums > Microsoft Technical Newsgroups > PowerShell

Using WPF from PowerShell...

Update your Vista Drivers Update Your Drivers Now!!
Closed Thread
 
Thread Tools Display Modes
Old 12-03-2006   #1 (permalink)
Serge van den Oever [Macaw]
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 SpecsSystem Spec
Old 12-05-2006   #2 (permalink)
Bruce Payette [MSFT]
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 SpecsSystem Spec
Old 12-08-2006   #3 (permalink)
Serge van den Oever [Macaw]
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 SpecsSystem Spec
Closed Thread
Update your Vista Drivers Update Your Drivers Now!!

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


Vistax64.com is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media 2005-2008

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51