{"id":15315,"date":"2018-07-12T06:00:27","date_gmt":"2018-07-12T13:00:27","guid":{"rendered":"https:\/\/www.sapien.com\/blog\/?p=15315"},"modified":"2018-07-30T13:58:31","modified_gmt":"2018-07-30T20:58:31","slug":"powershell-studio-how-to-prevent-powershell-cmdlets-from-hanging-in-gui-apps","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2018\/07\/12\/powershell-studio-how-to-prevent-powershell-cmdlets-from-hanging-in-gui-apps\/","title":{"rendered":"PowerShell Studio: How to prevent Powershell cmdlets from hanging in GUI apps"},"content":{"rendered":"<p>We have seen issues reported in our support forum where Azure commands are not terminating, or more likely their cmdlets are not returning in a GUI environment.\u00a0This is due to the Powershell pipeline being held up by the GUI, which could prevent Powershell from processing internal messages and events thus causing a hang when a cmdlet waits for these triggers.<\/p>\n<p>AzureRM cmdlets are meant to be executed from a Powershell console. The fact that we can extend this to a Windows application is a wonderful idea. Now we are indeed thinking\u00a0<em>out-of-the-box<\/em>!<\/p>\n<h3>What&#8217;s Going On?<\/h3>\n<p>Windows applications are\u00a0<em>synchronous<\/em>\u2014the user must wait until they complete. Unfortunately, as explained previously there will be occasions when event-driven tasks may not complete without any warning.<\/p>\n<p>When working with Azure commands everything happens in the cloud. There is the possibility that executed commands may have completed on Azure without you knowing.<\/p>\n<p>Fortunately, there is a convenient way to overcome this issue.<\/p>\n<h3>Asynchronous &#8211; Way To Go!<\/h3>\n<p>The <em>asynchronous<\/em> method involves submitting the task as a background job to be executed. When working from the GUI, as soon as the job is submitted, the control returns back to the GUI.<\/p>\n<p>PowerShell provides some cmdlets for submitting jobs in the background:<\/p>\n<p><em>Start-Job<\/em><br \/>\n<em>Get-Job<\/em><br \/>\n<em>Receive-Job<\/em><\/p>\n<p>A number of the Azure cmdlets have the \u2018<em>-AsJob<\/em>\u2018 parameter which can be used to submit Azure commands as individual jobs to be processed in the background.<\/p>\n<p>Here are some AzureRM cmdlets with the &#8216;<em>-AsJob<\/em>&#8216; parameter:<\/p>\n<p><em>New-AzureRmStorageAccount<\/em><br \/>\n<em>Remove-AzureRmResourceGroup<\/em><br \/>\n<em>New-AzureRmVM<\/em><br \/>\n<em>Stop-AzureRmVM<\/em><br \/>\n<em>Start-AzureRmVM<\/em><\/p>\n<p>One thing to remember\u2014submitting individual jobs will require the necessary logic to track them.<\/p>\n<h3>Building Code<\/h3>\n<p>The following is a basic console example of how we can accomplish creating a job and tracking its progress:<\/p>\n<ul>\n<li>Prepare the scriptblock for the job to stop an AzureRm VM:<\/li>\n<\/ul>\n<pre>## - Create Scriptblock for the job:\r\n$StopVmScript1 = {\r\n\r\n## - SignOn to Azure:\r\nImport-AzureRmContext -Path \"c:\\Temp\\WinPS_AsubRMprofile.json\";\r\n\r\n## - Run Azure cmdlet with AsJob parameter:\r\n$AzQryVMStop1 = Stop-AzureRMVM `\r\n-ResourceGroupName \"JaxItProCamp2018Resources\" `\r\n-Name 'Win2K16VM1' `\r\n-Force;\r\n};<\/pre>\n<ul>\n<li>Send the job for background execution and track the status:<\/li>\n<\/ul>\n<pre>## - Send\/Start job in background with a jobname:\r\nStart-Job -ScriptBlock $StopVmScript1 -Name \"bg_StopVM1Script\";\r\n\r\n## - Loop to check for The Stop-AzureRM cmdlet job completion:\r\ndo {\r\nStart-Sleep -Seconds 2;\r\n}\r\nwhile ((Get-Job).State -ne 'Completed');\r\n\r\n## - Get background job results:\r\nGet-job -Name \"bg_StopVM1Script\" | Format-List | Out-File -FilePath 'C:\\Temp\\GetBackgroundJobResults.txt';<\/pre>\n<p>This code can be tested and debugged at the Powershell console before being copied to the Windows Button control event. This code is just a starting point and can be enhanced.<\/p>\n<h3>Code GUI Implementation<\/h3>\n<p>Implementing this code in a GUI application will require more changes depending on the application requirements.\u00a0In this test we only have two controls in the form:<\/p>\n<ol>\n<li>The Button Control is used to prepare the Azure task and submit the job to execute in the background.<\/li>\n<li>The RichTextBox Control is used to post the job progress and result.<\/li>\n<\/ol>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2018\/06\/Azure_GUI_01_2018-06-29_17-00-20.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-15317\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2018\/06\/Azure_GUI_01_2018-06-29_17-00-20-300x131.jpg\" alt=\"\" width=\"623\" height=\"272\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/06\/Azure_GUI_01_2018-06-29_17-00-20-300x131.jpg 300w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/06\/Azure_GUI_01_2018-06-29_17-00-20-768x336.jpg 768w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/06\/Azure_GUI_01_2018-06-29_17-00-20-848x371.jpg 848w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/06\/Azure_GUI_01_2018-06-29_17-00-20.jpg 976w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/a><\/p>\n<p>Here is a sample implementation of the Powershell code in a Windows Button Control named &#8220;<strong>$buttonAzStopVMJob_Click<\/strong>&#8220;:<\/p>\n<pre>$buttonStopVMJob_Click={\r\n#TODO: Place custom script here\r\n$buttonStopVMJob.Enabled = $false;\r\n\r\n## - Create Scriptblock for the job:\r\n$StopVmScript1 = {\r\n\r\n## - Sign-On to Azure:\r\nImport-AzureRmContext -Path 'c:\\Temp\\WinPS_AsubRMprofile.json' | Out-Null;\r\n\r\n## - Run Azure cmdlet with AsJob parameter:\r\nStop-AzureRMVM -ResourceGroupName \"GlobalAzureBootCampResources\" `\r\n-Name 'Win2K16VM1' `\r\n-Force;\r\n}\r\n\r\n## - Send\/Start job in background with a jobname:\r\n$RichTextBoxStatus.AppendText(\"`r`nStart Job to Stop VM!`r`n\");\r\nStart-Job -ScriptBlock $StopVmScript1 -Name \"bgStopVM1Script\";\r\n\r\n## - Loop to check for The Stop-AzureRM cmdlet job completion:\r\ndo {\r\n$RichTextBoxStatus.AppendText(\"Process Stopping VM!`r`n\");\r\nStart-Sleep -Seconds 20;\r\n}\r\nwhile ((Get-Job -Name \"bgStopVM1Script\").State -ne 'Completed');\r\n\r\n## - Enable button when background job is done:\r\n$buttonStopVMJob.Enabled = $true;\r\n$RichTextBoxStatus.AppendText(\"Process Completed - VM Stopped!`r`n\");\r\n\r\n## - Get and Save to the file the background job results:\r\nGet-job -Name \"bgStopVM1Script\" | Format-List | Out-File -FilePath 'C:\\Temp\\GetBackgroundJobResults.txt';\r\nStart-Sleep -Seconds 2;\r\n\r\n## - Display the background job results:\r\n$RichTextBoxStatus.AppendText(\"`r`nDisplaying Asynch Job Results:`r`n\");\r\n$RichTextBoxStatus.AppendText((Get-Content -Path 'C:\\Temp\\GetBackgroundJobResults.txt' | Out-String -Width 1000));\r\n}<\/pre>\n<p>This code will create one job result:<\/p>\n<ol>\n<li>The background job results from the submitted Scriptblock.<\/li>\n<\/ol>\n<p>The results of this asynchronous process will be displayed in the GUI form under the RichTextBox object:<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-15332\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20-300x250.jpg\" alt=\"\" width=\"616\" height=\"513\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20-300x250.jpg 300w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20-768x640.jpg 768w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20-1024x854.jpg 1024w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20-848x707.jpg 848w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/Azure_GUI_05_2018-06-29_17-00-20.jpg 1030w\" sizes=\"auto, (max-width: 616px) 100vw, 616px\" \/><\/a><\/p>\n<p><em>Note: PowerShell Studio has a \u201cJob Tracker\u201d control set to manage jobs within your GUI. We will cover this topic in a future article.<\/em><\/p>\n<h3>Summary<\/h3>\n<p>This sample code provides the foundation for you to start thinking about how to prepare any Azure task to take advantage of background processing while the Azure task simultaneously processes smoothly. Now you can take it to the next level!<\/p>\n<p>You can download the sample Windows GUI here:\u00a0<a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2018\/07\/AzStopVMJob_sample.zip\" target=\"_blank\" rel=\"noopener\">AzStopVMJob_sample<\/a>.<\/p>\n<p>Stay tuned for a future blog article where we will discuss SAPIEN&#8217;s JobTracker helper functions in the wizard template &#8220;Grid Job&#8221; form.<\/p>\n<h3>Related Articles<\/h3>\n<ul>\n<li><a href=\"https:\/\/info.sapien.com\/index.php\/guis\/gui-scripting\/powershell-gui-apps-why-think-in-events\">PowerShell GUI Apps: Why think in events?<\/a><\/li>\n<li><a href=\"https:\/\/info.sapien.com\/index.php\/guis\/gui-advanced-tips\/powershell-studio-creating-responsive-forms\">PowerShell Studio: Creating Responsive Forms<\/a><\/li>\n<\/ul>\n<h3>Feedback<\/h3>\n<p>As always, if you have any ideas, comments, or feedback, please\u00a0<a href=\"https:\/\/www.sapien.com\/forums\/viewforum.php?f=23\" target=\"_blank\" rel=\"noopener\">visit our feedback forum<\/a>\u00a0and reference this post.<\/p>\n<p>&nbsp;<\/p>\n<p><em>Max Trinidad is a Technology Evangelist at SAPIEN Technologies Inc., and a Microsoft PowerShell MVP. You can reach him at\u00a0<a href=\"mailto:maxt@sapien.com\">maxt@sapien.com<\/a><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We have seen issues reported in our support forum where Azure commands are not terminating, or more likely their cmdlets are not returning in a GUI environment.\u00a0This is due to the Powershell pipeline being held up by the GUI, which could prevent Powershell from processing internal messages and events thus causing a hang when a [&hellip;]<\/p>\n","protected":false},"author":47,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[1054,946,1143,703,25],"tags":[65,1259,41,1022,28,1016],"class_list":["post-15315","post","type-post","status-publish","format-standard","hentry","category-automation","category-guiprogramming","category-powershell","category-powershell-studio","category-windows-powershell","tag-automation","tag-azure","tag-gui","tag-guiprogramming","tag-powershell","tag-powershell-studio"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/15315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/47"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=15315"}],"version-history":[{"count":25,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/15315\/revisions"}],"predecessor-version":[{"id":15615,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/15315\/revisions\/15615"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=15315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=15315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=15315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}