{"id":75431,"date":"2015-11-27T00:01:00","date_gmt":"2015-11-27T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/11\/27\/beginning-use-of-powershell-runspaces-part-2\/"},"modified":"2019-07-29T15:18:17","modified_gmt":"2019-07-29T23:18:17","slug":"beginning-use-of-powershell-runspaces-part-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/beginning-use-of-powershell-runspaces-part-2\/","title":{"rendered":"Beginning Use of PowerShell Runspaces: Part 2"},"content":{"rendered":"<p><b style=\"font-size: 12px;\">Summary<\/b><span style=\"font-size: 12px;\">:\u00a0Boe Prox presents some tips about beginning use with runspaces.<\/span><\/p>\n<p>Honorary Scripting Guy and Cloud and Datacenter Management MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy.<\/p>\n<p><b>Note<\/b>\u00a0\u00a0\u00a0This is a four-part series that includes the following posts:<\/p>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/beginning-use-of-powershell-runspaces\" target=\"_blank\" rel=\"noopener noreferrer\">Beginning Use of PowerShell Runspaces: Part 1<\/a>\u00a0\u00a0\u00a0Begin use with runspaces.<\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/beginning-use-of-powershell-runspaces-part-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">Beginning Use of PowerShell Runspaces: Part 2<\/a>\u00a0\u00a0\u00a0Begin use with runspaces.<\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/beginning-use-of-powershell-runspaces-part-3\" target=\"_blank\" rel=\"noopener noreferrer\">Beginning Use of PowerShell Runspaces: Part 3<\/a>\u00a0\u00a0Use runspace pools for multithreading.<\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-a-look-at-the-poshrsjob-module\/\" target=\"_blank\" rel=\"noopener noreferrer\">A Look at the PoshRSJob Module<\/a>\u00a0\u00a0\u00a0Learn about a module for working with runspaces.<\/li>\n<\/ul>\n<p>Yesterday,\u00a0we spent some time looking at how we can create a runspace that can be used to run a command in the background while leaving our console wide open for us to continue running commands. Although using what we have learned will make it easier to push commands to the background, we are currently limited to only running what we have in the script block.<\/p>\n<p>This means that we have to throw everything into the script block to run. This doesn\u2019t allow us to dynamically create variables or to have parameters to use to run against a collection of items. Fortunately, we have this capability when working with runspaces, but we have to make sure that everything is done correctly; otherwise, we may have some unforeseen issues.<\/p>\n<p>Why can\u2019t we simply create variables outside of the script block, run the commands in the runspace, and wait for our results to come rolling in? Well, the following example shows how this might not fare so well.<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell = [powershell]::Create()<\/p>\n<p style=\"margin-left: 30px;\">$Global:Param1 = &#8216;Param1&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$Global:Param2 = &#8216;Param2&#8217;<\/p>\n<p style=\"margin-left: 30px;\">[void]$PowerShell.AddScript({<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 [pscustomobject]@{<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param1 = $Param1<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param2 = $Param2<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 }<\/p>\n<p style=\"margin-left: 30px;\">})<\/p>\n<p style=\"margin-left: 30px;\">#Invoke the command<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Invoke()<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Dispose()<\/p>\n<p style=\"margin-left: 30px;\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1_RunspaceArgs.png\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1_RunspaceArgs.png\" alt=\"Image of command output\" \/><\/a><\/p>\n<p>Yes, the <b>Global<\/b> is intentional to show you that regardless of the type of scope that you give the variable, it will not work within the runspace. It simply outputs an object that consists of nothing useful.<\/p>\n<p>To get the desired results, we need to make use of a method called <b>AddArgument()<\/b>, and give it our data. There are some things to keep in mind when using this approach. First, you must have a <b>Param()<\/b> statement within your script block so it can populate the variables. Even more importantly, you must be aware of the order that you supply the arguments with each <b>AddArgument()<\/b> method. If you switch the order of what is being added, you will have issues, for example:<\/p>\n<p style=\"margin-left: 30px;\">$Param1 = &#8216;Param1&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$Param2 = &#8216;Param2&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell = [powershell]::Create()<\/p>\n<p style=\"margin-left: 30px;\">[void]$PowerShell.AddScript({<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0 \u00a0Param ($Param1, $Param2)<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 [pscustomobject]@{<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param1 = $Param1<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param2 = $Param2<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 }<\/p>\n<p style=\"margin-left: 30px;\">}).AddArgument($Param2).AddArgument($Param1)<\/p>\n<p style=\"margin-left: 30px;\">#Invoke the command<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Invoke()<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Dispose()<\/p>\n<p style=\"margin-left: 30px;\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2_RunspaceParams.png\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2_RunspaceParams.png\" alt=\"Image of command output\" \/><\/a><\/p>\n<p>This doesn\u2019t work out that well. Order is absolutely important in this approach. This code will work out much better:<\/p>\n<p style=\"margin-left: 30px;\">$Param1 = &#8216;Param1&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$Param2 = &#8216;Param2&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell = [powershell]::Create()<\/p>\n<p style=\"margin-left: 30px;\">[void]$PowerShell.AddScript({<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 Param ($Param1, $Param2)<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 [pscustomobject]@{<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param1 = $Param1<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param2 = $Param2<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 }<\/p>\n<p style=\"margin-left: 30px;\">}).AddArgument($Param1).AddArgument($Param2)<\/p>\n<p style=\"margin-left: 30px;\">#Invoke the command<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Invoke()<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Dispose()<\/p>\n<p>This is nice, but we can make it a little easier by using the <b>AddParameter()<\/b> method instead. This gives us an easier approach to specifying the proper variables with the parameters without the need to worry about the order of adding the data. The only thing that you must be aware of is that the parameter name must match what is in the <b>Param()<\/b> statement in the script block so it maps correctly.<\/p>\n<p>We have two options for adding parameters. The first is to individually add them, such as <b>.AddParameter(\u2018Param1\u2019,$Param1)<\/b>. This works, but if you start adding several parameters to a runspace, you may have to get creative with how you format your code.<\/p>\n<p style=\"margin-left: 30px;\">$Param1 = &#8216;Param1&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$Param2 = &#8216;Param2&#8217;<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell = [powershell]::Create()<\/p>\n<p style=\"margin-left: 30px;\">[void]$PowerShell.AddScript({<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 Param ($Param1, $Param2)<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 [pscustomobject]@{<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param1 = $Param1<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param2 = $Param2<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 }<\/p>\n<p style=\"margin-left: 30px;\">}).AddParameter(&#8216;Param2&#8217;,$Param2).AddParameter(&#8216;Param1&#8217;,$Param1) #Order won&#8217;t matter now<\/p>\n<p style=\"margin-left: 30px;\">#Invoke the command<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Invoke()<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Dispose()<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/1616.3.PNG\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/1616.3.PNG\" alt=\"Image of command output\" \/><\/a><\/p>\n<p>A more useful approach is to create a hash table with the parameter name and its value. Then supply that to the <b>AddParameters()<\/b> method, which will take each item in the hash table and map them to what you have in <b>Param()<\/b>.<\/p>\n<p style=\"margin-left: 30px;\">$ParamList = @{<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 Param1 = &#8216;Param1&#8217;<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 Param2 = &#8216;Param2&#8217;<\/p>\n<p style=\"margin-left: 30px;\">}<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell = [powershell]::Create()<\/p>\n<p style=\"margin-left: 30px;\">[void]$PowerShell.AddScript({<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 Param ($Param1, $Param2)<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 [pscustomobject]@{<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param1 = $Param1<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Param2 = $Param2<\/p>\n<p style=\"margin-left: 30px;\">\u00a0\u00a0\u00a0 }<\/p>\n<p style=\"margin-left: 30px;\">}).AddParameters($ParamList)<\/p>\n<p style=\"margin-left: 30px;\">#Invoke the command<\/p>\n<p style=\"margin-left: 30px;\">$PowerShell.Invoke()<\/p>\n<p>We have the same output as we got previously, but now have better looking code to go along with it!<\/p>\n<p>Now we have covered how to handle parameters within a runspace. Tomorrow, we will continue our dive into runspaces by looking at runspace pools and the world of multithreading our commands!<\/p>\n<p>I invite you to follow the Scripting Guy on\u00a0<a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\" rel=\"noopener noreferrer\">Twitter<\/a>\u00a0and\u00a0<a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\" rel=\"noopener noreferrer\">Facebook<\/a>. If you have any questions, send email to the Scripting Guy at\u00a0<a href=\"mailto:scripter@microsoft.com\" target=\"_blank\" rel=\"noopener noreferrer\">scripter@microsoft.com<\/a>, or post your questions on the\u00a0<a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\" rel=\"noopener noreferrer\">Official Scripting Guys Forum<\/a>. Until then, see ya!<\/p>\n<p><b>Boe Prox<\/b>, Windows PowerShell MVP and Honorary Scripting Guy<span style=\"font-size: 12px;\">\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary:\u00a0Boe Prox presents some tips about beginning use with runspaces. Honorary Scripting Guy and Cloud and Datacenter Management MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. Note\u00a0\u00a0\u00a0This is a four-part series that includes the following posts: Beginning Use of PowerShell Runspaces: Part 1\u00a0\u00a0\u00a0Begin use with runspaces. Beginning Use of [&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":[162,56,650,3,45],"class_list":["post-75431","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-boe-prox","tag-guest-blogger","tag-runspace","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary:\u00a0Boe Prox presents some tips about beginning use with runspaces. Honorary Scripting Guy and Cloud and Datacenter Management MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. Note\u00a0\u00a0\u00a0This is a four-part series that includes the following posts: Beginning Use of PowerShell Runspaces: Part 1\u00a0\u00a0\u00a0Begin use with runspaces. Beginning Use of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/75431","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=75431"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/75431\/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=75431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=75431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=75431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}