32 or 64 bit version of product: 64 bit
Operating system: Windows 10
32 or 64 bit OS: 64 bit
I'm trying to get some of my previous PowerShell scripts into a GUI. One that I use has multiple jobs (PS cmdlet Start-Job). Some jobs run in parallel and others wait for a previous job to complete before they start. I'm hoping to use the Start Job control because the jobs I'm running now cause the GUI to become unresponsive. I have read the PowerShell Studio: Creating Responsive Forms article but my ignorance doesn't help with finding the answer there.
I've attached what is just the code as it comes out-of-the-box for the Button - Start Job control and a couple of added items.
What I need help with is how to add additional jobs to the start job. So, is it possible and if yes, how, do I add additional jobs to the start job control? For example, add:
$scriptblock = {
start-sleep -s 3
write-output "step 3 complete"
write-output "step 4 complete"
}
Thanks in advance for any help.
- $form1_Load={
- #TODO: Initialize Form Controls here
- }
- $buttonStartJob_Click={
- $buttonStartJob.Enabled = $false
- $textbox1.AppendText("Start Job Button selected`r`n")
- #Create a New Job using the Job Tracker
- $paramAddJobTracker = @{
- Name = 'JobName'
- JobScript = {
- #--------------------------------------------------
- #TODO: Set a script block
- #Important: Do not access form controls from this script block.
- Param ($Argument1) #Pass any arguments using the ArgumentList parameter
- start-sleep -s 3
- write-output "step 1 complete`r`n"
- write-output "step 2 complete`r`n"
- for ($i = 0; $i -lt 50; $i++) { Start-Sleep -Milliseconds 100 }
- #--------------------------------------------------
- }
- ArgumentList = $null
- CompletedScript = {
- Param ([System.Management.Automation.Job]$Job)
- $results = Receive-Job -Job $Job
- $textbox1.AppendText($results)
- #Enable the Button
- $textbox1.AppendText("Completed Script`r`n")
- $buttonStartJob.ImageIndex = -1
- $buttonStartJob.Enabled = $true
- }
- UpdateScript = {
- Param ([System.Management.Automation.Job]$Job)
- $textbox1.AppendText("Update Script`r`n")
- #$results = Receive-Job -Job $Job -Keep
- #Animate the Button
- if ($null -ne $buttonStartJob.ImageList)
- {
- if ($buttonStartJob.ImageIndex -lt $buttonStartJob.ImageList.Images.Count - 1)
- {
- $buttonStartJob.ImageIndex += 1
- }
- else
- {
- $buttonStartJob.ImageIndex = 0
- }
- }
- }
- }
- Add-JobTracker @paramAddJobTracker
- }
- $jobTracker_FormClosed=[System.Windows.Forms.FormClosedEventHandler]{
- #Event Argument: $_ = [System.Windows.Forms.FormClosedEventArgs]
- #Stop any pending jobs
- Stop-JobTracker
- }
- $timerJobTracker_Tick={
- Update-JobTracker
- }
- #region Job Tracker
- $JobTrackerList = New-Object System.Collections.ArrayList
- function Add-JobTracker
- {
- <#
- .SYNOPSIS
- Add a new job to the JobTracker and starts the timer.
- .DESCRIPTION
- Add a new job to the JobTracker and starts the timer.
- .PARAMETER Name
- The name to assign to the job.
- .PARAMETER JobScript
- The script block that the job will be performing.
- Important: Do not access form controls from this script block.
- .PARAMETER ArgumentList
- The arguments to pass to the job.
- .PARAMETER CompletedScript
- The script block that will be called when the job is complete.
- The job is passed as an argument. The Job argument is null when the job fails.
- .PARAMETER UpdateScript
- The script block that will be called each time the timer ticks.
- The job is passed as an argument. Use this to get the Job's progress.
- .EXAMPLE
- Add-JobTracker -Name 'JobName' `
- -JobScript {
- Param($Argument1)#Pass any arguments using the ArgumentList parameter
- #Important: Do not access form controls from this script block.
- Get-WmiObject Win32_Process -Namespace "root\CIMV2"
- }`
- -CompletedScript {
- Param($Job)
- $results = Receive-Job -Job $Job
- }`
- -UpdateScript {
- Param($Job)
- #$results = Receive-Job -Job $Job -Keep
- }
- .LINK
- #>
- Param(
- [ValidateNotNull()]
- [Parameter(Mandatory=$true)]
- [string]$Name,
- [ValidateNotNull()]
- [Parameter(Mandatory=$true)]
- [ScriptBlock]$JobScript,
- $ArgumentList = $null,
- [ScriptBlock]$CompletedScript,
- [ScriptBlock]$UpdateScript)
- #Start the Job
- $job = Start-Job -Name $Name -ScriptBlock $JobScript -ArgumentList $ArgumentList
- if($null -ne $job)
- {
- #Create a Custom Object to keep track of the Job & Script Blocks
- $members = @{ 'Job' = $Job;
- 'CompleteScript' = $CompletedScript;
- 'UpdateScript' = $UpdateScript}
- $psObject = New-Object System.Management.Automation.PSObject -Property $members
- [void]$JobTrackerList.Add($psObject)
- #Start the Timer
- if(-not $timerJobTracker.Enabled)
- {
- $timerJobTracker.Start()
- }
- }
- elseif($null -ne $CompletedScript)
- {
- #Failed
- Invoke-Command -ScriptBlock $CompletedScript -ArgumentList $null
- }
- }
- function Update-JobTracker
- {
- <#
- .SYNOPSIS
- Checks the status of each job on the list.
- #>
- #Poll the jobs for status updates
- $timerJobTracker.Stop() #Freeze the Timer
- for($index = 0; $index -lt $JobTrackerList.Count; $index++)
- {
- $psObject = $JobTrackerList[$index]
- if($null -ne $psObject)
- {
- if($null -ne $psObject.Job)
- {
- if ($psObject.Job.State -eq 'Blocked')
- {
- #Try to unblock the job
- Receive-Job $psObject.Job | Out-Null
- }
- elseif($psObject.Job.State -ne 'Running')
- {
- #Call the Complete Script Block
- if($null -ne $psObject.CompleteScript)
- {
- #$results = Receive-Job -Job $psObject.Job
- Invoke-Command -ScriptBlock $psObject.CompleteScript -ArgumentList $psObject.Job
- }
- $JobTrackerList.RemoveAt($index)
- Remove-Job -Job $psObject.Job
- $index-- #Step back so we don't skip a job
- }
- elseif($null -ne $psObject.UpdateScript)
- {
- #Call the Update Script Block
- Invoke-Command -ScriptBlock $psObject.UpdateScript -ArgumentList $psObject.Job
- }
- }
- }
- else
- {
- $JobTrackerList.RemoveAt($index)
- $index-- #Step back so we don't skip a job
- }
- }
- if($JobTrackerList.Count -gt 0)
- {
- $timerJobTracker.Start()#Resume the timer
- }
- }
- function Stop-JobTracker
- {
- <#
- .SYNOPSIS
- Stops and removes all Jobs from the list.
- #>
- #Stop the timer
- $timerJobTracker.Stop()
- #Remove all the jobs
- while($JobTrackerList.Count -gt 0)
- {
- $job = $JobTrackerList[0].Job
- $JobTrackerList.RemoveAt(0)
- Stop-Job $job
- Remove-Job $job
- }
- }
- #endregion