Multi monitor script

Welcome Forums General PowerShell Q&A Multi monitor script

This topic contains 2 replies, has 3 voices, and was last updated by

 
Keymaster
8 months ago.

  • Author
    Posts
  • #95919

    Participant
    Points: 13
    Rank: Member

    Hi, I have copied / pasted / fudged together the script below and now need some advice on the next bit. Basically the script will be launched by a scheduled task created by SCCM to install a firmware upgrade of the users machine. When they click install it calls another ps script that actually does the upgrade. The issue I have is that we have a lot of users with multiple screens and their main screen will not always be the top most left in a pod or their left screen in on the desk. I have thought of generating a blank form that is a mile high by a mile wide to cover all of their screens but it will miss the top left or left screen if this is not the main screen. Also I dont know where to insert the blank form generation in the code below as it is my first play with XAML forms. Any help would be great
    please note I have taken out the below to make it easier to debug 🙂
    WindowState="Maximized"
    WindowStyle="None"

    $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"

    Update-Display -control TextDisplay -Property Text -Value $DisplayText

    $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 = "some powershell script.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()

  • #95930

    Participant
    Points: 2
    Rank: Member

    I responded to your other post. Looks like it is in the review queue for the moderator, but you should be able to see it soon.

  • #95943

    Keymaster
    Points: 12
    Team Member
    Rank: Member

    Just popped it in. Spam queue is acting weird lately.

The topic ‘Multi monitor script’ is closed to new replies.