This is the latest installment in our video series on working with Azure cmdlets in background jobs. In this example we are executing the PowerShell script in a Windows GUI Application.
View the video here: SAPIEN PowerShell Studio: GUI Working with Azure Cmdlets In Background Jobs
Minor Sample Script Changes
As the sample script evolves to execute the job from a Windows GUI application instead of the Console, depending on the script complexity more changes might be needed to interact with the GUI components.
The sample script executes the Stop-AzureRMVM cmdlet using the -AsJob parameter which will capture more information about the cmdlet being sent as a job:
: ## - Run Azure cmdlet with AsJob parameter: Stop-AzureRMVM -ResourceGroupName "GlobalAzureBootCampResources" ` -Name $Name ` -AsJob ` -Force -Verbose; :
The date/time format will display the processing information in the RichTextBox “$DisplayText” object:
: $t = Get-Date; $DisplayText.AppendText("`r`nBackground Process Started - $($JobName) - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))") :
Sample GUI Application
The sample GUI Application has two controls: Button, and RichTextBox.
The Button executes the code that will send the jobs to the background, and the RichTextBox is the area that will display the result of the task submitted by the button.
You can download the updated sample Windows GUI here: AzStopVMJob_GUI_sample_asJob.
Sample Code
This is the modified code used in the button control:
$buttonAzStopVMJob_Click = { #TODO: Place custom script here $buttonAzStopVMJob.Enabled = $false; #region RunStop-AzureRMVM_WithAsJobParam ## 2 - Run Stop-AzureRMVM cmdlet with the -AsJob parameter: ## - Create Scriptblock for the job: $JobName = "StopVmCmdletAsJob"; $JobScript = { param ($Name) ## - Sign-On to Azure: Import-AzureRmContext -Path 'C:\Temp\WinPS_AsubRMprofile.json' | Out-Null; $TaskName = "StopVM1_$($Name)"; ## - Run Azure cmdlet with AsJob parameter: Stop-AzureRMVM -ResourceGroupName "GlobalAzureBootCampResources" ` -Name $Name ` -AsJob ` -Force -Verbose; ## - Inside Job Loop to check for the cmdlet job completion: $t = Get-Date; "`r`nCmdlet Job Process Started - $TaskName - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))" do { Start-Sleep -Seconds 20; $t = Get-Date; "Cmdlet Job Processing! $TaskName - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))" } while ((Get-Job).State -ne 'Completed'); $t = Get-Date; "Cmdlet Job Process Ended - $TaskName - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))" "`r`nScriptblock - Getting Get-Job Results:" Get-Job | Format-List "Scriptblock - Getting Receive-Job Results:" Receive-Job * -Keep | Format-List } ## - Send/Start job in background with a jobname: $DisplayText.AppendText("`r`nStart Job to Stop VM!`r`n"); ## - Step that submit the scriptblock as a background job - ## $job = Start-Job -Name $JobName -ScriptBlock $JobScript -ArgumentList 'Win2K16VM1'; ## - Loop to check for The Stop-AzureRM cmdlet job completion: $t = Get-Date; $DisplayText.AppendText("`r`nBackground Process Started - $($JobName) - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))") do { Start-Sleep -Seconds 20; $t = Get-Date; $DisplayText.AppendText("`r`nProcessing Job - $($JobName) - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))") } while ((Get-Job).State -ne 'Completed'); $t = Get-Date; $DisplayText.AppendText("`r`nBackground Process Completed - $($JobName) - $(($t).ToString("MM/dd/yyyy - HH:mm:ss"))"); ## - Enable button when background job is done: $buttonAzStopVMJob.Enabled = $true; $DisplayText.AppendText("`r`nProcess Completed - VM Stopped!`r`n"); ## - Display the background job results: $DisplayText.AppendText("`r`nDisplaying Receive-Job from Stop-AzureRM AsJob Results:`r`n"); $DisplayText.AppendText((Receive-Job -Job $job -Keep | Out-String -Width 1000)); ## - Display Azure Stop-AzureRM cmdlet job results: $DisplayText.AppendText("`r`nDisplaying Get-Job Main Task Results:`r`n"); $DisplayText.AppendText((Get-Job | Format-List | Out-String -Width 1000)); #endregion RunStop-AzureRMVM_WithAsJobParam }
Feel free to copy/paste this code and modify as necessary.
Summary
The sample script underwent some minor changes to interact with the GUI application. Please reference the related links below for more details.
Stay tuned for a future blog article where we will discuss SAPIEN’s JobTracker helper functions in the wizard template “Grid Job” form.
Related Links
- PowerShell Studio: Working with Azure cmdlets in background jobs
- PowerShell Studio: How to prevent Powershell cmdlets from hanging in GUI apps
- PowerShell GUI Apps: Why think in events?
- PowerShell Studio: Creating Responsive Forms
Feedback
As always, if you have any ideas, comments, or feedback, please visit our feedback forum and reference this post.
Max Trinidad is a Technology Evangelist at SAPIEN Technologies Inc., and a Microsoft PowerShell MVP. You can reach him at maxt@sapien.com
Same issue as the first article:
The following line will not work in WMF 5.1:
while ((Get-Job).State -ne ‘Completed’);
This works:
while ((Get-Job).State -eq ‘Running’){}
The “{}” are required and the use of “Completed” will fail if the job status ends as “Failed”.
Good article. Keep it up.
I appreciate the comment!
Keep in mind, I’m using the “Do{..}While()” and not the “While()” by itself.
This is just an example I tested many times with Windows PowerShell 5.1 (Windows 10 Insider Build 17723) and, it can be done in different ways!
Is up to the scripter to make it better.
Sorry Max. I couldn’t see that as the code is hard to read. Someone should fix the code display in the forums and the blog. On many browsers it just looks like a mess with badly muted colors.
Note that the job status can be ‘Failed” and the loop will never end.
Here is another shortcut that you can leverage when using jobs:
$job = Stop-AzureRMVM …. -AsJob
$job.Status
The “$job” object is returned by all CmdLets that run as a job and the “Status” is dynamic. This eliminates the need for Get-Job when we have a “Job” object.
It’s optional as your code will work but using this can clarify and simplify code building.
It’s all good! The code provided is just a starting point and, as you mention, give room for improvements.
🙂