I have the below script that I need to run from a task schedule
in powershell if I type c:\form\multiscreen.ps1 it runs fine
In the cmd prompt if I type
C:\Users\sbrookma>powershell.exe -executionpolicy bypass -file c:\form\multiscreen.ps1
nothing happens
Is this because it is opening up in a different thread ?
$Global:syncHash = [hashtable]::Synchronized(@{})
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
# Load WPF assembly if necessary
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
$psCmd = [PowerShell]::Create().AddScript({
[xml]$xaml = @"
"@
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$syncHash.Window=[Windows.Markup.XamlReader]::Load( $reader )
[xml]$XAML = $xaml
$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
#Find all of the form types and add them as members to the synchash
$syncHash.Add($_.Name,$syncHash.Window.FindName($_.Name) )
}
$Script:JobCleanup = [hashtable]::Synchronized(@{})
$Script:Jobs = [system.collections.arraylist]::Synchronized((New-Object System.Collections.ArrayList))
#region Background runspace to clean up jobs
$jobCleanup.Flag = $True
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("jobCleanup",$jobCleanup)
$newRunspace.SessionStateProxy.SetVariable("jobs",$jobs)
$jobCleanup.PowerShell = [PowerShell]::Create().AddScript({
#Routine to handle completed runspaces
Do {
Foreach($runspace in $jobs) {
If ($runspace.Runspace.isCompleted) {
[void]$runspace.powershell.EndInvoke($runspace.Runspace)
$runspace.powershell.dispose()
$runspace.Runspace = $null
$runspace.powershell = $null
}
}
#Clean out unused runspace jobs
$temphash = $jobs.clone()
$temphash | Where {
$_.runspace -eq $Null
} | ForEach {
$jobs.remove($_)
}
Start-Sleep -Seconds 1
} while ($jobCleanup.Flag)
})
$jobCleanup.PowerShell.Runspace = $newRunspace
$jobCleanup.Thread = $jobCleanup.PowerShell.BeginInvoke()
#endregion Background runspace to clean up jobs
Function Update-Display {
Param (
$Control,
$Property,
$Value,
[switch]$AppendContent
)
# This is kind of a hack, there may be a better way to do this
If ($Property -eq "Close") {
$syncHash.Window.Dispatcher.invoke([action]{$syncHash.Window.Close()},"Normal")
Return
}
# This updates the control based on the parameters passed to the function
$syncHash.$Control.Dispatcher.Invoke([action]{
# This bit is only really meaningful for the TextBox control, which might be useful for logging progress steps
If ($PSBoundParameters['AppendContent']) {
$syncHash.$Control.AppendText($Value)
} Else {
$syncHash.$Control.$Property = $Value
}
}, "Normal")
}
$DisplayText = "
This is a TextBlock control
with multiple lines of text.
3rd Line
4th Line
This is a TextBlock control This is a TextBlock control
with multiple lines of text. This is a TextBlock control
3rd Line
4th Line
This is a TextBlock control This is a TextBlock control
with multiple lines of text. This is a TextBlock control
3rd Line
4th Line
This is a TextBlock control
with multiple lines of text.
3rd Line
4th Line
This is a TextBlock control This is a TextBlock control
with multiple lines of text. This is a TextBlock control
3rd Line
4th Line
This is a TextBlock control This is a TextBlock control
with multiple lines of text. This is a TextBlock control
3rd Line
4th Line"
Update-Display -control TextDisplay -Property Text -Value $DisplayText
#region screenblocker
Add-Type -AssemblyName System.Windows.Forms
$screens = [System.Windows.Forms.Screen]::Allscreens | Where-Object Primary -eq $false
$synchash.screens = New-Object System.Collections.Generic.List[System.Object]
foreach($screen in $screens){
$synchash.screens.Add($screen.devicename.replace('\','').replace('.','')[-1])
}
foreach ($screen in $screens){
$synchash."$($screen.devicename.replace('\','').replace('.',''))" = $screen
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
$PowerShell = [PowerShell]::Create().AddScript({
function LoadXaml ($filename){
$XamlLoader=(New-Object System.Xml.XmlDocument)
$XamlLoader.Load($filename)
return $XamlLoader
}
$screenNum = $synchash.screens[0]
$display = "Display" + $screenNum
$synchash.screens.RemoveAt(0)
$XamlMainWindow = LoadXaml("\blankScreen.xaml")
$reader = (New-Object System.Xml.XmlNodeReader $XamlMainWindow)
$syncHash."Window$screenNum" = [Windows.Markup.XamlReader]::Load($reader)
[xml]$XAML = $XamlMainWindow
$XamlMainWindow.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object{
#Find all of the form types and add them as members to the synchash
$syncHash.Add($("" + $_.Name + $screenNum),$syncHash."Window$screenNum".FindName($_.Name) )
}
$syncHash."Window$screenNum".Top = $synchash.$display.bounds.Top;
$syncHash."Window$screenNum".Left = $synchash.$display.bounds.Left;
$syncHash."Window$screenNum".Width = $synchash.$display.bounds.Width;
$syncHash."Window$screenNum".Height = $synchash.$display.bounds.Height;
$synchash."Window$screenNum".Show()
$synchash."error$screenNum" = $error
})
$PowerShell.Runspace = $newRunspace
[void]$Jobs.Add((
[pscustomobject]@{
PowerShell = $PowerShell
Runspace = $PowerShell.BeginInvoke()
}
))
}
#endregion screenblocker
$syncHash.Install.Add_Click({
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("SyncHash",$SyncHash)
$PowerShell = [PowerShell]::Create().AddScript({
Function Update-Window {
Param (
$Control,
$Property,
$Value,
[switch]$AppendContent
)
# This is kind of a hack, there may be a better way to do this
If ($Property -eq "Close") {
$syncHash.Window.Dispatcher.invoke([action]{$syncHash.Window.Close()},"Normal")
Return
}
# This updates the control based on the parameters passed to the function
$syncHash.$Control.Dispatcher.Invoke([action]{
# This bit is only really meaningful for the TextBox control, which might be useful for logging progress steps
If ($PSBoundParameters['AppendContent']) {
$syncHash.$Control.AppendText($Value)
} Else {
$syncHash.$Control.$Property = $Value
}
}, "Normal")
}
start-sleep -Milliseconds 850
$scripttorun = "c:\form\multiping.ps1"
update-window -Control Progress -Property Value -Value 25
start-sleep -Milliseconds 850
update-window -Control Progress -Property Value -Value 50
Invoke-Expression $scripttorun
start-sleep -Milliseconds 500
update-window -Control Progress -Property Value -Value 75
start-sleep -Milliseconds 200
update-window -Control Progress -Property Value -Value 100
})
$PowerShell.Runspace = $newRunspace
[void]$Jobs.Add((
[pscustomobject]@{
PowerShell = $PowerShell
Runspace = $PowerShell.BeginInvoke()
}
))
})
#region Window Close
$syncHash.Window.Add_Closed({
Write-Verbose 'Halt runspace cleanup job processing'
$jobCleanup.Flag = $False
#Stop all runspaces
$jobCleanup.PowerShell.Dispose()
})
#endregion Window Close
$syncHash.Window.ShowDialog() | Out-Null
$syncHash.Error = $Error
})
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()