I'm working on a GUI in PowerShell where I was throwing errors when certain comboboxes were clicked.
After the error was thrown, I could drop the combobox list down and see it's contents, but if I shifted to another combox on the same datagridview, I would get the same initial error before I could see the drop-down list.
I posted this in the TechNet PowerShell forums and got the answer that I needed to run my GUI in single threaded apartment (STA). PowerShell, by default, runs in MTA but you can overwrite this (in v2.0) by using the -STA
switch when calling powershell.exe
.
However, my GUI simply invokes the default PowerShell application (in MTA mode) so my question is, is there a way to programmatically set the apartmentstate from inside of my GUI/script?
If not, my next attempt would be to detect the apartment state and try to re-kick off my GUI from the initial load of my gui with something like:
powershell.exe -STA myguiprog.ps1
Edit:
So my workaround DOES work:
if ([threading.thread]::CurrentThread.GetApartmentState() -eq "MTA") {
& $env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exe -sta $MyInvocation.ScriptName
}
If you have pscx installed, you can use Invoke-Apartment -Apartment STA -Expression { .... }
.
If not, have a look at WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF ) where James creates runspace with STA. Another source might be Asynchronicity in PowerShell.
Or some older posts about custom cmdlet Single Threaded Apartment in PowerShell V1.
You can 'just use Invoke-Apartment' is rather a glib answer considering it does not come with Powershell. Nor should a developer assume code they wrote will always be on a machine where the owner took the time to install pscx.
The work-around to launch Powershell works if you are willing to alter the original environment. I use the PS ISE exclusively, so redriving my code from PS changes my experience. I also dislike hard coding where I think PS lives. One day Microsoft might change V1.0 (rather sill to keep using it for V2 and V3!) so you should really programmatically find what the user started and use that. As well as pass any parameters that were passed to you. To make the problem worse, when I go to Start/Accessories/Powershell - I have four choices of PS to run. The coded workaround forces a choice I may not have chosen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With