{"id":4522,"date":"2012-12-03T00:01:00","date_gmt":"2012-12-03T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/12\/03\/use-powershell-default-parameter-values-to-simplify-scripts\/"},"modified":"2012-12-03T00:01:00","modified_gmt":"2012-12-03T00:01:00","slug":"use-powershell-default-parameter-values-to-simplify-scripts","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-default-parameter-values-to-simplify-scripts\/","title":{"rendered":"Use PowerShell Default Parameter Values to Simplify Scripts"},"content":{"rendered":"<p><strong>Summary:<\/strong> Microsoft PowerShell MVP and guest blogger Dave Moravec talks about using default parameter values to simplify Windows PowerShell scripts.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Well, our European Tour is drawing down, but it&rsquo;s not over yet. Yesterday, we had a great time with Bartek in Warsaw, and last night we took the train back from Warsaw to Berlin.<\/p>\n<p>This morning, we are on a train to Prague to see Windows PowerShell MVP Dave Moravec. We will not have too much time&mdash;only about six hours before we have to hop back on a train to Frankfurt. But when Dave began talking to the Scripting Wife on Facebook and on Twitter, well, it was decided that we had the time, and we wanted to meet Dave. In honor of the occasion, I asked Dave to write a little bit about his favorite Windows PowerShell&nbsp;3.0 feature. I will admit I was a bit surprised by his choice&mdash;perhaps you will be as well.<\/p>\n<p>Take it away, Dave &hellip;<\/p>\n<p>I have been in the IT industry for 15 years. The last 10 years working mainly with Microsoft management technologies. I work for one of the biggest international accounting companies as an administrator responsible for System Center: Configuration Manager (SCCM). I like to automate my infrastructure-related tasks with Windows PowerShell. I&rsquo;m an author and speaker for Microsoft Czech Republic, and I run my own blog at&nbsp;<a href=\"http:\/\/powershell.cz\/\" target=\"_blank\">PowerShell.cz<\/a>. You can reach me on Twitter at&nbsp;<a href=\"https:\/\/twitter.com\/makovec\" target=\"_blank\">@makovec<\/a>.<\/p>\n<h2>Changing default parameter values<\/h2>\n<p>When I was asked to write about my favorite Windows PowerShell&nbsp;3.0 feature, my #1 <strong>$PSDefaultParameterValues<\/strong> came to mind immediately. From my point of view, this was something I was looking for, for a long time.<\/p>\n<p>How does it work? With <strong>$PSDefaultParameterValues<\/strong>, you can define (overwrite) default values of parameters for Windows PowerShell cmdlets. Actually, I just found that Scripting Guy already showed a nice usage of this a month ago in his <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2012\/11\/02\/powertip-automatically-format-your-powershell-table.aspx?Redirected=true\" target=\"_blank\">PowerTip: Automatically Format Your PowerShell Table<\/a>. Let me show you a few other practical examples.<\/p>\n<h2>How to set a default value<\/h2>\n<p>Let&rsquo;s imagine you work frequently with Windows PowerShell jobs (and I am sure you do!). So I will use a really complicated example:<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Start-Job -Name sj -ScriptBlock { $pid } | Wait-Job | Receive-Job<\/p>\n<p style=\"padding-left: 30px\">&nbsp; 8828<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Receive-Job -Name sj<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt;<\/p>\n<p>No result received, as expected. If you want to leave the data in queue, you have to use the &#8211;<strong>Keep<\/strong> switch parameter. By using <strong>$PSDefaultParameterValues<\/strong>, you can tell PowerShell to set &#8211;<strong>Keep<\/strong> to True every time. <strong>$PSDefaultParameterValues<\/strong> is a hash table where the Key is combination of <strong>CmdletName:ParameterName<\/strong> and Value is the actual value you want to assign. In our example, the assignment is:<\/p>\n<p style=\"padding-left: 30px\">&nbsp;PS&gt; $PSDefaultParameterValues = @{&#8216;Receive-Job:Keep&#8217;=$true}<\/p>\n<p>You see that for the <strong>Keep<\/strong> parameter of the <strong>Receive-Job<\/strong> cmdlet, we used variable <strong>$true<\/strong> (as it is a switch, True means it&rsquo;s enabled), so now we can write:<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Start-Job -Name sj2 -ScriptBlock { $pid } | Wait-Job | Receive-Job<\/p>\n<p style=\"padding-left: 30px\">&nbsp; 2433<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Receive-Job -Name sj2<\/p>\n<p style=\"padding-left: 30px\">&nbsp; 2432<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt;<\/p>\n<p>If you check <strong>$PSDefaultParameterValues<\/strong>, you can see that it&rsquo;s really a hash table.<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Receive-Job:Keep&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; True<\/p>\n<p>If you want to overwrite the actual default value, you can specify <strong>$false<\/strong> for <strong>Keep<\/strong> parameter<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Start-Job -Name sj3 -ScriptBlock { $pid } | Wait-Job | Receive-Job &ndash;Keep:$false<\/p>\n<p style=\"padding-left: 30px\">&nbsp; 998<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Receive-Job -Name sj3<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt;<\/p>\n<p>Another usage for <strong>$PSDefaultParameterValues<\/strong> I found relates to work with the <strong>Export-Csv<\/strong> cmdlet. I export a lot of data from our infrastructure very often and pass them on in CSV format to my boss. Therefore, I don&rsquo;t like the default behavior, which includes type info at the beginning of the file. I decided to change that. Furthermore, as work with different language settings, I also changed the delimiter.<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues = @{&#8216;Export-Csv:Delimiter&#8217;=&#8217;;&#8217;; &#8216;Export-Csv:NoTypeInformation&#8217;=$true}<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Get-Process -Name p* | Select Name, WS | Export-Csv -Path c:\\tmp\\ps.csv<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Get-Content C:\\tmp\\ps.csv<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &ldquo;Name&rdquo;;&rdquo;WS&rdquo;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &ldquo;powershell_ise&rdquo;;&rdquo;17477223&rsquo;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Export-Csv:Delimiter&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Export-Csv:NoTypeInformation&nbsp;&nbsp;&nbsp; True<\/p>\n<p>Works like a charm, but in the last output, you may have noticed an unpleasant surprise. Our modification from the first example (<strong>Receive-Job<\/strong>) disappeared. You probably discovered it happened during our second modification of <strong>$PSDefaultParameterValues<\/strong>. To avoid this, we will use techniques for work with the hash tables. There are two different possibilities:<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues[&#8216;Receive-Job:Keep&#8217;]=$true<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues.Add(&#8216;Enter-PSSession:ComputerName&#8217;, &#8216;localhost&#8217;)<\/p>\n<p>After that, two additional default values were received, and we should have four in total now. Let&rsquo;s check it:<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Export-Csv:Delimiter&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Receive-Job:Keep&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; True<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Export-Csv:NoTypeInformation&nbsp;&nbsp;&nbsp; True<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Enter-PSSession:ComputerName&nbsp;&nbsp;&nbsp; localhost<\/p>\n<p>You can immediately test newly added values. As of now, if you write <strong>Enter-PSSession<\/strong>, you will be connected to your local computer by default. This is probably not so useful, so feel free to modify it for the server you are mostly connecting to.<\/p>\n<p>There are other options for <strong>$PSDefaultParameterValues<\/strong> modification:<\/p>\n<ul>\n<li>$PSDefaultParameterValues = @{&#8216;Get-ChildItem:Force&#8217; = $true} will allow you to run <strong>dir<\/strong> command with force enabled, so you&rsquo;ll see hidden files and folders.<\/li>\n<li>$PSDefaultParameterValues = @{&#8216;*:Credential&#8217; = $cred} is very useful if you have your administrator credentials stored in a variable. As $PSDefaultParameterValues supports wild cards. This example will use these credentials for all cmdlets supporting it.<\/li>\n<li>Do you know people who are adjusting their watch ten minutes ahead? Let&rsquo;s replicate this in Windows PowerShell: $PSDefaultParameterValues = @{&#8216;Get-Date:Date&#8217; = {[System.DateTime]::Now.AddMinutes(10)}} Here I used the possibility of $PSDefaultParameterValues to use ScriptBlock as value for the parameter.<\/li>\n<\/ul>\n<p>The last one was a bit funny, I know. You can also do some awful assignments, but I will not show you any examples.<\/p>\n<h2>Changing the default value<\/h2>\n<p>If you want to change the actual value, you can use a standard operation used for work with the hash tables. We will change the delimiter for the <strong>Export-Csv<\/strong> cmdlet:<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues[&lsquo;Export-Csv:Delimiter&rsquo;]=&rsquo;%&rsquo;<\/p>\n<p>Now all my exported CSVs will be delimited by the percent sign. If I don&rsquo;t like it, I can overwrite the behavior as I did in the first example with <strong>Receive-Job<\/strong>.<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Get-Process &ndash;Name p* | Select Name, WS | Export-Csv &ndash;Path c:\\tmp\\ps.csv &ndash;Delimiter &lsquo;,&rsquo;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; Get-Content c:\\tmp\\ps.csv<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &ldquo;Name&rdquo;,&rdquo;WS&rdquo;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &ldquo;powershell_ise&rdquo;,&rdquo;17477223&rsquo;<\/p>\n<h2>Removing the default value<\/h2>\n<p>If you want to remove your settings from <strong>$PSDefaultParameterValues<\/strong>, you can remove just a single record, or you can remove all records at once. Removing a single record is as easy as adding one; just use <strong>Remove<\/strong> method of the hash table:<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues.Remove(&lsquo;Enter-PSSession:ComputerName&rsquo;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp; PS&gt; $PSDefaultParameterValues<\/p>\n<p>Removing the whole variable is arranged by using the <strong>Remove-Variable<\/strong> cmdlet. As this variable is automatic, <strong>Remove-Variable<\/strong> cleans its content only. As the Windows PowerShell team is full of clever people, they invented an additional option&mdash;temporarily disabling <strong>$PSDefaultParameterValues<\/strong>. You can set its <strong>Disable <\/strong>key to True and after that any of <strong>$PSDefaultParameterValues<\/strong> will apply.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5123.hsg-12-3-12-1.jpg\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5123.hsg-12-3-12-1.jpg\" alt=\"Image of command output\" \/><\/a><\/p>\n<p>You can see how it works from the above image. I removed all actual values from <strong>$PSDefaultParameterValues<\/strong> and then set <strong>Delimiter<\/strong> for <strong>Export-Csv<\/strong>. The next lines contain testing of disabled and enabled functionality of <strong>$PSDefaultParameterValues<\/strong>. As a confirmation, you see the content of all three exported files.<\/p>\n<h2>A few extra tips<\/h2>\n<p>You are probably aware of scoping in Windows PowerShell (if not, please read the <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh847849.aspx\" target=\"_blank\">about_Scopes<\/a> Help file). If you define <strong>$PSDefaultParameterValues<\/strong> in your Global scope, it will be inherited to your script or function scope. This can sometimes lead to a really bad side effect. You can use disabling of <strong>$PSDefaultParameterValues<\/strong> in this case.<\/p>\n<p>The second point you need to be aware of is that <strong>$PSDefaultParameterValues<\/strong> is active in your current session. If you have some useful assignments, you have to define it in your profile script.<\/p>\n<p>For further investigation of the <strong>$PSDefaultParameterValues<\/strong> concept, see <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh847819\" target=\"_blank\">about_Parameters_Default_Values<\/a>.<\/p>\n<p>~David<\/p>\n<p>Thank you, David, for an excellent article.<\/p>\n<p>I 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=\"mailto: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.<\/p>\n<p><strong>Ed Wilson, Microsoft Scripting Guy<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft PowerShell MVP and guest blogger Dave Moravec talks about using default parameter values to simplify Windows PowerShell scripts. Microsoft Scripting Guy, Ed Wilson, is here. Well, our European Tour is drawing down, but it&rsquo;s not over yet. Yesterday, we had a great time with Bartek in Warsaw, and last night we took the [&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":[391,56,362,2,3,4,45],"class_list":["post-4522","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-david-moravec","tag-guest-blogger","tag-powershell-3","tag-running","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft PowerShell MVP and guest blogger Dave Moravec talks about using default parameter values to simplify Windows PowerShell scripts. Microsoft Scripting Guy, Ed Wilson, is here. Well, our European Tour is drawing down, but it&rsquo;s not over yet. Yesterday, we had a great time with Bartek in Warsaw, and last night we took the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4522","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=4522"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4522\/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=4522"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=4522"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=4522"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}