{"id":2798,"date":"2013-09-29T00:01:00","date_gmt":"2013-09-29T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2013\/09\/29\/weekend-scripter-max-out-powershell-in-a-little-bit-of-timepart-2\/"},"modified":"2013-09-29T00:01:00","modified_gmt":"2013-09-29T00:01:00","slug":"weekend-scripter-max-out-powershell-in-a-little-bit-of-timepart-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-max-out-powershell-in-a-little-bit-of-timepart-2\/","title":{"rendered":"Weekend Scripter: Max Out PowerShell in a Little Bit of Time&#8212;Part 2"},"content":{"rendered":"<p><strong>Summary<\/strong>: Microsoft PFE, Jason Walker, talks about improving performance of Windows PowerShell by using runspaces.\nMicrosoft Scripting Guy, Ed Wilson, is here. <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/jason+walker\/\" target=\"_blank\">Jason Walker<\/a> is back with us today for the conclusion of his two-part weekend series. Be sure to read yesterday&rsquo;s post before you read today&rsquo;s:<\/p>\n<p style=\"padding-left: 30px\"><a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2013\/09\/28\/weekend-scripter-max-out-powershell-in-a-little-bit-of-time.aspx\" target=\"_blank\">Weekend Scripter: Max Out PowerShell in a Little Bit of Time&mdash;Part 1<\/a>\nAnd now, Jason&hellip;\nYesterday we explored using Windows PowerShell remoting (<strong>Invoke-Command<\/strong>) and Windows PowerShell jobs, and we ended with a teaser about runspaces. Today let&rsquo;s take a closer look at runspaces.\nGuest blogger, Boe Prox previously wrote about using runspaces: <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2012\/04\/17\/expert-commentary-2012-scripting-games-advanced-event-2.aspx\" target=\"_blank\">Expert Commentary: 2012 Scripting Games Advanced Event 2<\/a>. In his post, he links to Windows PowerShell MVP, Dr. Tobias Weltner&rsquo;s, video, which explains some of the advantages of using runspaces. I recommend that you check it out.\nThe basic steps to leverage runspaces are as follows:<\/p>\n<ol start=\"1\">\n<li>Create the runspace pool.<\/li>\n<li>Open the runspace pool.<\/li>\n<li>Create a Windows PowerShell object to the run commands.<\/li>\n<li>Specify which runspace the Windows PowerShell object will use.<\/li>\n<li>Add the commands.<\/li>\n<li>Invoke the command.<\/li>\n<li>Get the results from the command.<\/li>\n<li>Clean up the Windows PowerShell object and runspace pool.<\/li>\n<\/ol>\n<p>Here are the steps in Windows PowerShell:<\/p>\n<p style=\"padding-left: 30px\">#Create the runspace pool<\/p>\n<p style=\"padding-left: 30px\">$RunspacePool = [RunspaceFactory]::CreateRunspacePool()<\/p>\n<p style=\"padding-left: 30px\">#Open the runspace pool<\/p>\n<p style=\"padding-left: 30px\">$RunspacePool.Open()<\/p>\n<p style=\"padding-left: 30px\">#Create PowerShell object<\/p>\n<p style=\"padding-left: 30px\">$Powershell = [PowerShell]::Create()<\/p>\n<p style=\"padding-left: 30px\">#Specify the runspace to use<\/p>\n<p style=\"padding-left: 30px\">$Powershell.RunspacePool = $RunspacePool<\/p>\n<p style=\"padding-left: 30px\">#Add the command to run<\/p>\n<p style=\"padding-left: 30px\">$Powershell.AddCommand(&#8220;Get-Process&#8221;)<\/p>\n<p style=\"padding-left: 30px\">#Invoke the command<\/p>\n<p style=\"padding-left: 30px\">$Runspace= $PowerShell.BeginInvoke()<\/p>\n<p style=\"padding-left: 30px\">#Get the results of the command<\/p>\n<p style=\"padding-left: 30px\">$PowerShell.EndInvoke($Runspace)<\/p>\n<p style=\"padding-left: 30px\">#Clean up<\/p>\n<p style=\"padding-left: 30px\">$PowerShell.Dispose()<\/p>\n<p style=\"padding-left: 30px\">$RunspacePool.Close()\nFor us to run this asynchronously against multiple servers, we have to make a few modifications to the example. To demonstrate, I will explain how this is done by using the <strong>Get-WinEvent<\/strong> example from yesterday.<\/p>\n<ol start=\"1\">\n<li>Define a list of servers to run the cmdlet against:<\/li>\n<\/ol>\n<p style=\"padding-left: 60px\">$Computers = &ldquo;mail01&rdquo;,&rdquo;mail02&rdquo;,&rdquo;mbx01&rdquo;,&rdquo;mbx02&rdquo;,&rdquo;mbx03&rdquo;<\/p>\n<ol start=\"2\">\n<li>Create an empty array that we will use later in the script:<\/li>\n<\/ol>\n<p style=\"padding-left: 60px\">$RunspaceCollection = @()<\/p>\n<ol start=\"3\">\n<li>Call the <strong>CreateRunspacePool <\/strong>method and specify a minimum and maximum amount of runspaces that are allowed to be open. These parameters are explained in the Windows Dev Center: <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/dd324626(v=vs.85).aspx\" target=\"_blank\">RunspaceFactory.CreateRunspacePool Method (Int32, Int32, PSHost)<\/a>.<\/li>\n<\/ol>\n<p style=\"padding-left: 30px\">The following example creates a runspace pool with a minimum of 1 runspace and a maximum of 5:<\/p>\n<p style=\"padding-left: 60px\">$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1,5)<\/p>\n<ol start=\"4\">\n<li>Define a script block (the cmdlet and arguments we want to run) that we will supply to the Windows PowerShell object:<\/li>\n<\/ol>\n<p style=\"padding-left: 60px\">$ScriptBlock = {<\/p>\n<p style=\"padding-left: 60px\">&nbsp;Param($Computer)<\/p>\n<p style=\"padding-left: 60px\">Get-Process -ComputerName $Computer -FilterHashtable @{Logname=&#8217;System&#8217;;Id=1074} -MaxEvents 10 }<\/p>\n<ol start=\"5\">\n<li>Because we want to run <strong>Get-WinEvent<\/strong> asynchronously across multiple servers, we need to create multiple Windows PowerShell objects. Then we will add the script block that we created and the unique computer name to that Windows PowerShell object. A <strong>Foreach<\/strong> loop will make quick work of this task:<\/li>\n<\/ol>\n<p style=\"padding-left: 60px\">Foreach($Computer in $Computers){<\/p>\n<p style=\"padding-left: 60px\">&nbsp;#Create a PowerShell object to run add the script and argument.<\/p>\n<p style=\"padding-left: 60px\">&nbsp; $Powershell = [PowerShell]::Create().AddScript($ScriptBlock).AddArgument($Computer)<\/p>\n<p style=\"padding-left: 60px\">&nbsp;<\/p>\n<p style=\"padding-left: 60px\">&nbsp; #Specify runspace to use<\/p>\n<p style=\"padding-left: 60px\">&nbsp; $Powershell.RunspacePool = $RunspacePool<\/p>\n<p style=\"padding-left: 60px\">&nbsp;<\/p>\n<p style=\"padding-left: 60px\">&nbsp; #Create Runspace collection<\/p>\n<p style=\"padding-left: 60px\">&nbsp; [Collections.Arraylist]$RunspaceCollection += New-Object -TypeName PSObject -Property @{<\/p>\n<p style=\"padding-left: 60px\">&nbsp;&nbsp; Runspace = $PowerShell.BeginInvoke()<\/p>\n<p style=\"padding-left: 60px\">&nbsp;&nbsp; PowerShell = $PowerShell&nbsp;&nbsp;<\/p>\n<p style=\"padding-left: 60px\">&nbsp; }<\/p>\n<p style=\"padding-left: 60px\">&nbsp;<\/p>\n<p style=\"padding-left: 60px\">}<\/p>\n<ol start=\"6\">\n<li>You&rsquo;ll notice that we also added the Windows PowerShell object to the runspace pool. We then created a <strong>PSObject<\/strong> that contains the Windows PowerShell object, and we defined and invoked the runspace. To get the results of the runspace, we have to call the <strong>EndInvoke<\/strong> method from the Windows PowerShell object that contains the runspace. This <strong>PSObject<\/strong> acts as a collection that keeps everything nicely packaged.<\/li>\n<li>The only thing left to do is check for the runspace to be completed. When it is complete, we retrieve the results. I like to use a <strong>While<\/strong> loop for this type of task:<\/li>\n<\/ol>\n<p style=\"padding-left: 60px\">While($RunspaceCollection){<\/p>\n<p style=\"padding-left: 60px\">&nbsp;Foreach($Runspace in $RunspaceCollection.ToArray()){<\/p>\n<p style=\"padding-left: 60px\">&nbsp; If($Runspace.Runspace.IsCompleted){<\/p>\n<p style=\"padding-left: 60px\">&nbsp;&nbsp; $Runspace.PowerShell.EndInvoke($Runspace.Runspace)<\/p>\n<p style=\"padding-left: 60px\">&nbsp;&nbsp; $Runspace.PowerShell.Dispose()<\/p>\n<p style=\"padding-left: 60px\">&nbsp;&nbsp; $RunspaceCollection.Remove($Runspace)<\/p>\n<p style=\"padding-left: 60px\">&nbsp; }<\/p>\n<p style=\"padding-left: 60px\">&nbsp;}<\/p>\n<p style=\"padding-left: 60px\">&nbsp;<\/p>\n<p style=\"padding-left: 60px\">}\nThe <strong>EndInvoke<\/strong> method is used to retrieve the results from the completed runspace. Finally, we clean up. That&rsquo;s all there is to multithread commands in Windows PowerShell using runspaces.\nYou can download a more complete solution from the TechNet Gallery: <a href=\"http:\/\/gallery.technet.microsoft.com\/Get-AsyncEvent-multi-Get-ed5c68c3\" target=\"_blank\">Get-AsyncEvent multi thread Get-WinEvent using runspaces<\/a>.<\/p>\n<p style=\"padding-left: 30px\"><strong>Note<\/strong>&nbsp; &nbsp;<strong>Get-AsyncEvent<\/strong> is written as a function, so you need to dot source the .ps1 file before you can run the function inside it. For more information, see <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/08\/09\/how-do-i-use-a-windows-powershell-script-containing-functions.aspx\" target=\"_blank\">How Do I Use a Windows PowerShell Script Containing Functions?<\/a>\n~Jason\nThank you, Jason, for this weekend&rsquo;s blog posts and for sharing your time and knowledge.\nI invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.\n<strong>Ed Wilson, Microsoft Scripting Guy<\/strong>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft PFE, Jason Walker, talks about improving performance of Windows PowerShell by using runspaces. Microsoft Scripting Guy, Ed Wilson, is here. Jason Walker is back with us today for the conclusion of his two-part weekend series. Be sure to read yesterday&rsquo;s post before you read today&rsquo;s: Weekend Scripter: Max Out PowerShell in a Little [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[56,338,60,3,4,61,45],"class_list":["post-2798","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-guest-blogger","tag-jason-walker","tag-performance","tag-scripting-guy","tag-scripting-techniques","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft PFE, Jason Walker, talks about improving performance of Windows PowerShell by using runspaces. Microsoft Scripting Guy, Ed Wilson, is here. Jason Walker is back with us today for the conclusion of his two-part weekend series. Be sure to read yesterday&rsquo;s post before you read today&rsquo;s: Weekend Scripter: Max Out PowerShell in a Little [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/2798","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=2798"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/2798\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=2798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=2798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=2798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}