{"id":1976,"date":"2015-04-02T00:00:00","date_gmt":"2015-04-01T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/a-plethora-of-powershell-pitfalls\/"},"modified":"2016-12-09T15:07:56","modified_gmt":"2016-12-09T15:07:56","slug":"a-plethora-of-powershell-pitfalls","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/","title":{"rendered":"A Plethora of PowerShell Pitfalls"},"content":{"rendered":"<ul class=\"series-articles\">\n<li class=\"series-articles--active\">\n<p>A Plethora of PowerShell Pitfalls Part 1: Pesky Parameter Problems<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\">A Plethora of PowerShell Pitfalls Part 2:\u00a0 A Portion of Potential Puzzles<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/the-poster-of-the-plethora-of-powershell-pitfalls\/\">The Poster for a Plethora of PowerShell Pitfalls: Pretty Powerful Panaceas<\/a><\/p>\n<\/li>\n<\/ul>\n<h2>Pesky Parameter Problems<\/h2>\n<p class=\"start\">Many articles out there sing the praises of PowerShell. In fact, I have had several of my own published here on Simple-Talk. And, indeed, PowerShell can provide a tremendous boost in productivity for administrative-type tasks. However, as with any complex technology there are a variety of ways-some a lot more obvious than others-that you can cause problems for yourself without even realizing it. This article presents some of my favorite pitfalls, culled from my own experiences as well as from monitoring user questions on StackOverflow.<\/p>\n<p>This article is designed to truly engage your brain. To get the most out of it I recommend:<\/p>\n<ol>\n<li>First, try to answer the short list of questions <i>without executing the code<\/i>. Exercise your mental muscles. Give it some thought. Try to figure out the <code>what<\/code>.<\/li>\n<li>Next, go ahead and execute the code to see if you were right. If not, now given the answers, see if you understand the <code> why<\/code>.<\/li>\n<li>Finally, continue reading through the answers and explanations to reveal the <code>what<\/code> and the <code> why<\/code>.<\/li>\n<\/ol>\n<h2>The Questions<\/h2>\n<p>Try to answer these questions before executing the code.<\/p>\n<h3 id=\"Toc414818189\">Question 1<\/h3>\n<p>This function should square a number and report some diagnostic output with it, i.e. write some text to the console.<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">function square($x) {\r\n\u00a0\u00a0\u00a0 Write-Output \"Squaring $x...\"\r\n\u00a0\u00a0\u00a0 return $x * $x\r\n}  \r\n<\/pre>\n<p>What is the result of executing this statement?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$y = 4 + (square 5)  \r\n<\/pre>\n<h3 id=\"Toc414818190\">Question 2<\/h3>\n<p>You want to generate a (very:-) terse report to give an indication of how many XML files you have. What are the likely outcomes from executing this statement?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$myList = Get-ChildItem *.xml; if ($myList.Count -gt 100) {\"big\"} else {\"small\"}  \r\n<\/pre>\n<h3 id=\"Toc414818191\">Question 3<\/h3>\n<p>Given that the left side is equivalent to the right side for both of these scenarios&#8230;<\/p>\n<table class=\"GridTable4-Accent11\">\n<tbody>\n<tr>\n<td valign=\"top\">\n<p><b>Multiple Assignments<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b>Individual Assignments<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>$a = $b = $c = &#8220;thing&#8221;<\/p>\n<\/td>\n<td valign=\"top\">\n<p>$a = &#8220;thing&#8221;<\/p>\n<p>$b = &#8220;thing&#8221;<\/p>\n<p>$c = &#8220;thing&#8221;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>$a, $b = 1, 2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>$a = 1<\/p>\n<p>$b = 2<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>What are the values for <code>$a<\/code> and <code>$b<\/code> upon executing this line?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a, $b= 1,2 * 3  <\/pre>\n<h3 id=\"Toc414818192\">Question 4<\/h3>\n<p>Consider a function that takes in a number and a switch parameter that indicates whether to negate the given number or not:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">function f([int]$num, [switch]$negate)\r\n{\r\n\u00a0\u00a0\u00a0 if ($negate) { -$num } else { $num }\r\n}  \r\n\r\n<\/pre>\n<p>What is the result of executing this statement?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f -num42 -Negate $false  <\/pre>\n<h3 id=\"Toc414818193\">Question 5<\/h3>\n<p>(a) Given that the <code>if<\/code> statement below displays &#8220;I am true&#8221; on the console, how many times will the <code>while<\/code> loop display &#8220;hello&#8221; ?<\/p>\n<pre>$condition1 = $false -eq ''\r\n$condition2 = '' -eq $false\r\nif ($condition1) { \"I am true\" }\r\nwhile ($condition1 -and $condition2) { \"hello\" }  \r\n\u00a0\r\n<\/pre>\n<p>(b) Given that the third line below prints the result &#8220;3&#8221; (the number of items in the list), what is output on the fourth line?<\/p>\n<pre>$myList = 'a','b','c'\r\n$anotherItem = 'd'\r\n$myList.Length\r\n($anotherItem + $myList).Length\r\n\u00a0\r\n<\/pre>\n<h3>Question 6<\/h3>\n<p>Given this function definition&#8230;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">function f($a, $b, $c)\r\n{\r\n\u00a0\u00a0\u00a0 Write-output \"Processing...\"\r\n\u00a0\u00a0\u00a0 if ($b -eq $null -or $c.Length -lt 5) { Write-Output 'one' }\r\n\u00a0\u00a0\u00a0 elseif ($a -is [int]) { Write-Output 'two' }\r\n\u00a0\u00a0\u00a0 else { Write-Output 'three' }\r\n}\r\n<\/pre>\n<p>What is the output of this statement?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f  25,true,'some string' <\/pre>\n<h2 id=\"Toc414818194\">The Answers<\/h2>\n<p>As with most endeavors, the more you put in the more you get out, so have a go at answering the above question before continuing on to the answers. Each exposition below repeats the question but this time with the answer. Challenge yourself yet a second time: see if you can figure out why you get the given answer before reading the subsequent explanation.<\/p>\n<h3>Question 1: Functions Return Unexpected Results<\/h3>\n<div class=\"question\">\n<h4>Question<\/h4>\n<p><i>This function should square a number and report some diagnostic output with it, i.e. write some text to the console.<\/i><\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tfunction square($x) {\r\n\t\u00a0\u00a0\u00a0 Write-Output \"Squaring $x...\"\r\n\t\u00a0\u00a0\u00a0 return $x * $x\r\n\t}  \r\n<\/pre>\n<p><i>What is the result of executing this statement?<\/i><\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t$y = 4 + (square 5)  \r\n\t<\/pre>\n<h4>Answer<\/h4>\n<pre>\tMethod invocation failed because [System.Object[]] does not contain a method named 'op_Addition'.<\/pre>\n<\/div>\n<p>Because (a) the <code>return<\/code> keyword in a function is optional, and (b) both function return values and the <code>Write-Output<\/code> cmdlet send output to the stdout stream, and (c) the <code>Write-Output<\/code> cmdlet can be invoked without even using the cmdlet name, then one can easily get unexpected output when calling a function.<\/p>\n<p>There are two types of functions in PowerShell:<\/p>\n<ol>\n<li>A function that does work but returns no result; it serves as a container to logically group several other statements.<\/li>\n<li>A function that returns a result.<\/li>\n<\/ol>\n<p>Here is a function of type A that performs several long-running steps and writes messages to the <code>stdout<\/code> stream to let you know what step it is on.<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\tfunction ProcessAll()\r\n\t\t{\r\n\t\t\u00a0\u00a0\u00a0 Write-Output \"Processing A.\"\r\n\t\t\u00a0\u00a0\u00a0 DoProcessA\r\n\t\t\u00a0\u00a0\u00a0 Write-Output \"Processing B.\"\r\n\t\t\u00a0\u00a0\u00a0 DoProcessB\r\n\t\t\u00a0\u00a0\u00a0 Write-Output \"Done.\"\r\n\t\t}  \r\n<\/pre>\n<p>That works just as you would expect. In your PowerShell window, you will see this:<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\t\tPS&gt; ProcessAll\r\n\t\tProcessing A.\r\n\t\tProcessing B.\r\n\t\tDone.  \r\n\t\t<\/pre>\n<p>Here is a function of type B, a pure mathematical function:<\/p>\n<pre>\t\tfunction square($x) {\r\n\t\t\u00a0\u00a0\u00a0 return $x * $x\r\n\t\t}\r\n<\/pre>\n<p>This also works just as you would expect. Here we store the result of the calculation in a variable that displays the contents of that variable. I have added one more line to show that it is, in fact, an integer as expected.<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\t\t PS&gt; $result = square 3\r\n\t\tPS&gt; $result\r\n\t\t9  \r\n\t\tPS&gt; $result.GetType().Name\r\n\t\tInt32  \r\n\t\t<\/pre>\n<p>Problems arise when you attempt to create a function that is an A\/B hybrid. Pretend that squaring takes a very long time so you want to report progress inside the square function. Just as before add one or more <code>Write-Output<\/code> statements:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\tfunction square($x) {\r\n\t\t\u00a0\u00a0\u00a0 Write-Output \"Squaring $x...\"\r\n\t\t\u00a0\u00a0\u00a0 return $x * $x\r\n\t\t}  \r\n\t\t \r\n\t\t<\/pre>\n<p>Now we have a rather unexpected result:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\tPS[1]&gt; $result = square 3\r\n\t\t \r\n\t\tPS[2]&gt; $result\r\n\t\tSquaring 3...\r\n\t\t9  \r\n\t\tPS[3]&gt; $result.GetType().Name\r\n\t\tObject[]  \r\n\t\tPS[4]&gt; $y = 4 + (square 5)\r\n\t\tMethod invocation failed because [System.Object[]] does not contain a method named 'op_Addition'\r\n\t\t<\/pre>\n<p>It seemingly does everything as expected until you reveal the type-an array of objects instead of an integer-and the execution, which completely fails! As to why this happens, look closer at the execution above&#8230; shouldn&#8217;t the &#8220;Squaring 3&#8230;&#8221; message show up after statement [1], when you execute the function, rather than after statement [2], when you display the contents of the variable?<\/p>\n<p>The issue emanates from not understanding an important rule: A PowerShell function returns all uncaptured output.<\/p>\n<div class=\"quote\"><span class=\"style1\">&#8220;<\/span>A PowerShell function <br \/> returns all uncaptured output.<span class=\"style1\">&#8220;<\/span><\/div>\n<p>That is, the PowerShell <code>return<\/code> statement is a red herring. Yes, a function will return the value sent from a <code>return<\/code> statement but that is because it is uncaptured output, which just means output that is not stuffed into a variable or fed to a pipe. But, by that definition, the <code>Write-Output<\/code> statement also generates uncaptured output! So the value passed to <code>Write-Output<\/code> is also returned by the function. Thus, this function returns two items: the string &#8220;Squaring 3&#8230;&#8221; and the integer 9; in other words a 2-element array of objects.<\/p>\n<h4>The Fix<\/h4>\n<p>The principle fix for this is to not use Write-Output inside of type B functions. (Recall that the <code>Write-Output<\/code> keyword is itself optional: <code>\"hello\"<\/code> is the same as <code>Write-Output \"hello\"<\/code>, so you cannot use either form!) You could use Write-Host instead because its output stream is separate from stdout, but don&#8217;t! See Jeffrey Snover&#8217;s <a href=\"http:\/\/www.jsnover.com\/blog\/2013\/12\/07\/write-host-considered-harmful\/#!\">Write-Host Considered Harmful<\/a>. Instead use Write-Verbose, which writes to PowerShell&#8217;s separate verbose stream.<\/p>\n<p>But there is more to the story&#8230; You must be ever-diligent when writing type B functions, because some standard cmdlets or .NET method calls send output to the stdout stream. You must, by the above rule, capture their output to prevent interference with your function&#8217;s return value. Do this by using the PowerShell equivalent of \/dev\/null, which can be done in a variety of ways:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\t$any | Out-Null\r\n\t\t[void]$any\r\n\t\t$any &gt; $null\r\n\t\t$null = $any\r\n<\/pre>\n<div class=\"note\">\n<p class=\"note\"><strong>Advanced note<\/strong>: See Jason Archer&#8217;s <a href=\"http:\/\/stackoverflow.com\/a\/5263780\/115690\">Stack Overflow post<\/a> that evaluates the performance of each of these flavors, suggesting you shy away from <code>Out-Null<\/code>.<\/p>\n<\/div>\n<h3>Question 2: The Conundrum of None, One, or Many<\/h3>\n<div class=\"question\">\n<h4>Question<\/h4>\n<p><i>You want to generate a (very:-) terse report to give an indication of how many XML files you have. What are the likely outcomes from executing this statement?<\/i><\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t$myList = Get-ChildItem *.xml; if ($myList.Count -gt 100) {\"big\"} else {\"small\"}  \r\n\t<\/pre>\n<h4>Answer<\/h4>\n<p>1) &#8220;big&#8221;<br \/> 2) &#8220;small&#8221;<br \/> 3) The property &#8216;Count&#8217; cannot be found on this object. Verify that the property exists.<\/p>\n<p><em>you will only see this error if you have strict mode enabled, which is recommended (see <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/hh849692.aspx\">Set-StrictMode<\/a>).<\/em><\/p>\n<\/div>\n<p>The code in this question is a ticking time bomb &#8230;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$myList= Get-ChildItem *.xml;if ($myList.Count-gt 100) {\"big\"}else {\"small\"} <\/pre>\n<p>&#8230;that is to say that code <i>will<\/i> blow up at some point, the only question is when. If <code>Get-ChildItem<\/code> returns more than one item then the type of <code>$myList<\/code> is an array, which has a <code>Count<\/code> property, and the conditional statement will then report <i>big<\/i> or <i>small<\/i> as appropriate. But there are two other significant possibilities: if <code>Get-ChildItem<\/code> finds only one XML file, then <code>$myList<\/code> will not be an array, and not have a <code>Count<\/code> property. Worse, if there are no XML files <code>$myList<\/code> will be null, which does not have any properties. Thus, there are three rather than two likely outcomes from executing the above statement:<\/p>\n<ol>\n<li>big<\/li>\n<li>small<\/li>\n<li>Error: The property &#8216;Count&#8217; cannot be found on this object. Verify that the property exists.<\/li>\n<\/ol>\n<div class=\"note\">\n<p class=\"note\">Note that you will only see this error if you have strict mode enabled, which is recommended (see <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/hh849692.aspx\">Set-StrictMode<\/a>).<\/p>\n<\/div>\n<p>Typically <code>Get-ChildItem<\/code> returns an array of objects: the return type is Object[], which has a <code>Count<\/code> property that you can access. But if <code>Get-ChildItem<\/code> has only one item to return then it returns a single <code>FileInfo<\/code> (or <code>DirectoryInfo<\/code>) object, so the type is, of course <code>FileInfo<\/code> (or <code>DirectoryInfo<\/code>). Neither of these types has a <code>Count <\/code>property, so it will cause an error. Finally, if <code>Get-ChildItem<\/code> has no items to return, it returns null, which of course has neither a type nor any properties, so you will also get an error.<\/p>\n<h4>The Fix<\/h4>\n<div class=\"quote\"><span class=\"style1\">&#8220;<\/span>A function&#8217;s return type depends on<br \/> \u00a0the number of items returned.<span class=\"style1\">&#8220;<\/span><\/div>\n<p>There is a variety of ways to deal with this pervasive issue. Often the best course of action is to just to make sure that, whenever you <i>can<\/i> get an array,\u00a0 you <i>do<\/i> get an array. Here is one simple way to do that:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$myList= @(Get-ChildItem *.ps1); if ($myList.Count-gt 100) {\"big\"}else {\"small\"} <\/pre>\n<p>Here, the Count property will always exist and it will return 0, 1, or more as appropriate, thereby eliminating the opportunity for the above error.<\/p>\n<h3>Question 3: Multiple Assignment Not Delivering Expected Values<\/h3>\n<div class=\"question\">\n<h4>Question<\/h4>\n<p>What are the values for <code>$a<\/code> and <code>$b<\/code> upon executing this line?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t$a, $b = 1, 2 * 3<\/pre>\n<h4>Answer<\/h4>\n<p>$a is 1<\/p>\n<p>$b is @(2, 1, 2, 1, 2)<\/p>\n<\/div>\n<p>PowerShell provides a handy multiple-assignment mechanism that feels like it has an &#8220;array nature&#8221; to it, given that this statement assigns 1 to <code>$a<\/code> and 2 to <code>$b<\/code> simultaneously:<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-69327\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2015\/04\/figure.png\" width=\"175\" \/><\/p>\n<p>There are two common expectations as to what assignments that statement makes-<i>and both are wrong<\/i>!<\/p>\n<ol>\n<li>It seems reasonable to assume that we can apply other operators that maintain the array-like feel in this multiple assignment statement, i.e. <code>$a<\/code> should be 3 and <code>$b<\/code> should be 6:<br \/> <img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2168-img6B.gif\" alt=\"2168-img6B.gif\" width=\"175\" \/><\/li>\n<li>Alternatively, it seems reasonable that the multiply operator is just applied very locally, so that <code>$a<\/code> is assigned 1 while <code>$b<\/code> is assigned 6.<\/li>\n<\/ol>\n<p>But both of those are incorrect. Here is the actual result:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">PS[1]&gt; $a, $b = 1, 2 * 3\r\n\r\nPS[2]&gt; $a\r\n1\r\n\r\nPS[3]&gt; $b\r\n2\r\n1\r\n2\r\n1\r\n2  \r\n\t<\/pre>\n<p>The reason is operator precedence: the comma operator has higher precedence than the multiply operator. In other words:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a, $b = 1, 2 * 3\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 =&gt;\r\n$a, $b = (1, 2) * 3\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 =&gt;\r\n$a, $b = 1, 2, 1, 2, 1, 2\u00a0\u00a0\u00a0 =&gt;\r\n$a = 1; $b = 2, 1, 2, 1, 2  \r\n<\/pre>\n<p>To understand how to arrive at that last line, there is one more thing to know about multiple assignment. Each variable on the left is assigned exactly one value from the right-<i>except<\/i> when there are more values on the right, then all the left overs are also given to the last variable on the left! (See <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/hh847842.aspx\">about_Operator_Precedence<\/a> and <i>Assigning Multiple Variables<\/i> on PowerShell&#8217;s <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/hh847875.aspx\">about_Assignment_Operators<\/a> page for more.)<\/p>\n<h4>The Fix<\/h4>\n<p class=\"quote\"><span class=\"style1\">&#8220;<\/span>The comma has a higher<br \/> precedence than arithmetic <br \/> operators<\/p>\n<p>The comma has a higher precedence than arithmetic operators. Work <i>with<\/i> operator precedence rather than <i>against<\/i> it:<\/p>\n<p>If you want <code>$a<\/code> to be 1 and <code>$b<\/code> to be 6 you need only add parentheses to force it to comply:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a, $b= 1, (2* 3) <\/pre>\n<p>If, however, you do want the multiplication to apply to each element, you must be explicit:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a, $b= (1 *3), (2* 3) <\/pre>\n<div class=\"note\">\n<p><i>Advanced note: <\/i> For those thinking that, well, <i>that&#8217;s<\/i> not very PowerShell-like, there is a way, of course, that does leverage the array-nature of PowerShell:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a, $b =1, 2| % { $_* 3 } <\/pre>\n<p>\u00a0I leave it as an exercise to play with that to understand the details.<\/p>\n<\/div>\n<h3>Question 4: When a Boolean is Not Just a Boolean<\/h3>\n<div class=\"question\">\n<h4>Question<\/h4>\n<p>Consider a function that takes in a number and a switch parameter that indicates whether to negate the given number or not:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tfunction f([int]$num, [switch]$negate)\r\n\t{\r\n\t\u00a0\u00a0\u00a0 if ($negate) { -$num } else { $num }\r\n\t}  \r\n\t\r\n<\/pre>\n<p>What is the result of executing this statement?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tf -num 42 -Negate $false<\/pre>\n<h4>Answer<\/h4>\n<pre>\t-42<\/pre>\n<\/div>\n<p>PowerShell has two types of parameters: <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.switchparameter(v=vs.85).aspx\">SwitchParameters<\/a> and everything else. A <code>SwitchParameter<\/code> is typically used to specify a condition that is true or is false. For example, normally <code>Get-ChildItem<\/code> returns both files and directories, but if you use the <code>-Directory<\/code> switch, then it will return only directories:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">Get-ChildItem-Directory  <\/pre>\n<p>The <code>-Directory<\/code> switch when present says to restrict output to directories and when absent says to not restrict the output. So it looks and acts just like a Boolean-but it is not quite the same because it is a SwitchParameter rather than a regular parameter. The difference is crucial: when you specify a regular parameter you provide a value (Get-Process -Id <code>25<\/code> or Set-Location -Path <code>c:\\temp<\/code>). With a SwitchParameter, its presence or absence deter\u00c2\u00admines its Boolean state, rather than any value being passed to it. Because, in fact, you <i>cannot<\/i> pass a value to it! So the code in the question&#8230;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f -num42 -Negate $false  <\/pre>\n<p>&#8230;says to pass 42 to the <code>$num<\/code> parameter (-num 42), set the <code>$negate<\/code> SwitchParameter to true (-Negate), and, since the function f takes no more inputs, <i>ignore anything else on the line<\/i> ($false). Thus, all of these produce exactly the same result:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f -num 42 -Negate $false\r\nf -num 42 -Negate $true\r\nf -num 42 -Negate\r\n<\/pre>\n<h4>The Fix<\/h4>\n<p class=\"quote\"><span class=\"style1\">&#8220;<\/span>A switch parameter <br \/> does not take a value<span class=\"style1\">&#8220;<\/span><\/p>\n<p>Fairly obvious for this one: do not attempt to provide a value to a switch parameter.<\/p>\n<div class=\"note\">\n<div class=\"longnote\">\n<p><i>Advanced note:<\/i> As stated above, you cannot technically pass a value to a SwitchParameter because it does not have a value. But you <i>can<\/i> specify its state of existence. There are a couple ways to do that, the simplest being, for example:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f -num 42-Negate:$false  <\/pre>\n<p>You could also set the existence of the switch via command-line splatting, which is a more useful thing to do. See my <a href=\"http:\/\/stackoverflow.com\/a\/29158749\/115690\">StackOverflow post<\/a> for more details.<\/p>\n<\/div>\n<\/div>\n<h3>Question 5: A Question of Argument Placement<\/h3>\n<div class=\"question\">\n<p>(a) Given that the <code>if<\/code> statement below displays &#8220;I am true&#8221; on the console, how many times will the <code>while<\/code> loop display &#8220;hello&#8221; ?<\/p>\n<pre>\t$condition1 = $false -eq ''\r\n\t$condition2 = '' -eq $false\r\n\tif ($condition1) { \"I am true\" }\r\n\twhile ($condition1 -and $condition2) { \"hello\" }  \r\n<\/pre>\n<p>(b) Given that the third line below prints the result &#8220;3&#8221; (the number of items in the list), what is output on the fourth line?<\/p>\n<pre>\t$myList = 'a','b','c'\r\n\t$anotherItem = 'd'\r\n\t$myList.Length\r\n\t($anotherItem + $myList).Length\r\n\t\r\n<\/pre>\n<h4>Answer<\/h4>\n<ol style=\"list-style-type: lower-alpha;\">\n<li>0<\/li>\n<li>6<\/li>\n<\/ol>\n<\/div>\n<p>Both (a) and (b) in this question may produce seemingly unexpected results and they do so for exactly the same reason: whether PowerShell operators are commutative largely depends on the operands. In pure mathematics, addition is always commutative regardless of the arguments: 234.212 + 5 is the same as 5 + 234.212. Fear not: the same is true regarding addition of numbers in PowerShell. When it comes to comparison, evaluating &#8220;does 5 equal 3?&#8221; is the same as evaluating &#8220;does 3 equal 5?&#8221; in algebra, and again in PowerShell, the testing of equality of integers is commutative ( &#8216;3 -eq 5&#8217; yields the same result as &#8216;5 -eq 3&#8217; ).<\/p>\n<p>But the plus sign is overloaded in PowerShell: you could, for example, add strings and obviously &#8220;a&#8221; + &#8220;b&#8221; is not the same as &#8220;b&#8221; + &#8220;a&#8221; (&#8220;ab&#8221; vs &#8220;ba&#8221;). Thus, commutativity of the plus sign operator depends on the type of the arguments. On the other hand, the PowerShell equality operator &#8220;-eq&#8221; is always commutative, whether you are comparing integer with integer, string with string, etc.<\/p>\n<p>Where it gets interesting is when you apply operators to different types. Consider part (a) of the question. The answer is that the loop outputs &#8220;hello&#8221; zero times because <code>$condition1<\/code> is true but <code>$condition2<\/code> is false! How can that be? With dissimilar operand types, PowerShell attempts to coerce the right-hand operand to the type of the left-hand operand. For <code>$condition1<\/code>, the empty string is cast to a Boolean, and it evaluates to <code>$false<\/code>, so <code>$condition1<\/code> is really comparing <code>$false<\/code> to <code>$false<\/code>, so the result is true. For <code>$condition2<\/code>, <code>$false<\/code> is cast to the string &#8220;false&#8221; and thus it is really comparing the empty string to a 5-character string, with the result being false. (With thanks to mjolinor&#8217;s <a href=\"http:\/\/stackoverflow.com\/a\/26015506\/115690\">StackOverflow post<\/a> for the gist of this.)<\/p>\n<p>As to part (b) of the question, the answer is six rather than four as you might expect. First, consider if you reverse the arguments, <code>$myList + $anotherItem<\/code> adds one item to the 3-element array, yielding a 4-element array, so its length would be 4. But as stated in the question, <code>$anotherItem + $myList<\/code>, is not adding an element to an array. In fact, PowerShell applies the same automatic casting as with comparison operators: Here the left-hand side is a string, so it converts the right-hand side to a string, getting &#8220;a b c&#8221;. That code reduces to adding a string to a string, yielding &#8220;da b c&#8221;, and the length of that is 6. Thus in attempting to add an element to an array, the order of operands affects not just the order of the result, but whether the result even remains an array!<\/p>\n<h4>The Fix<\/h4>\n<p class=\"quote\"><span class=\"style1\">&#8220;&#8230; the o<\/span>rder of dissimilar <br \/> operands matters<span class=\"style1\">&#8220;<\/span><\/p>\n<p>For testing truth, always put the Boolean first, because the order of dissimilar operands matters. e.g. (<code>$true -eq\u00a0 $x<\/code>) rather than (<code>$x -eq $true<\/code>): \u00a0But you can also avoid the whole issue when it comes to Booleans by simply testing the truth of an expression directly. That is, line 1 is equivalent to line 2, and line 3 is equivalent to line 4:<\/p>\n<pre>PS[1]&gt; if ($true -eq $x) { \"true\" }\r\nPS[2]&gt; if ($x) { \"true\" }\r\n\t<\/pre>\n<pre>PS[3]&gt; if ($false -eq $x)\u00a0 { \"false\" }\r\nPS[4]&gt; if (!$x)\u00a0 { \"false\" }  \r\n\t<\/pre>\n<p>For the case of adding an element to an array, always put the array on the left when using a plus sign. Alternately, use the assignment-by-addition operator; these two lines are equivalent:<\/p>\n<pre>$myList= $myList +\"new item\"<\/pre>\n<pre>$myList+= \"new item\"  <\/pre>\n<div class=\"note\">\n<p class=\"note\"><i>Advanced note:<\/i> PowerShell lets you strongly type data but-in a similar way to the above discussion-<i>where<\/i> you put the typing matters. Both of these yield exactly the same, strongly-typed array of integers (without the type specification you would just have an array of objects):<\/p>\n<\/div>\n<pre class=\"lang:ps theme:powershell-ise\">[Int[]]$array1 = (1,2,3,4,5)\r\n$array2 = [Int[]](1,2,3,4,5)\r\n\r\n<\/pre>\n<p>If you display the type (e.g. $array1.GetType().FullName), the result is an array of integers ( System.Int32[] ) in both cases. However, if you then add an element to each array (e.g. $array1 += 6) then $array1 remains an array of integers but $array2 reverts to an array of objects! (With thanks to <a href=\"http:\/\/powershell.com\/cs\/blogs\/tips\/archive\/2010\/11\/11\/strongly-typed-arrays.aspx\">this post<\/a> on PowerShell.com.)<\/p>\n<h3>Question 6: Three-Card Monte<\/h3>\n<div class=\"question\">\n<h4>Question<\/h4>\n<p>Given this function definition&#8230;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tfunction f($a, $b, $c)\r\n\t{\r\n\t\u00a0\u00a0\u00a0 Write-output \"Processing...\"\r\n\t\u00a0\u00a0\u00a0 if ($b -eq $null -or $c.Length -lt 5) { Write-Output 'one' }\r\n\t\u00a0\u00a0\u00a0 elseif ($a -is [int]) { Write-Output 'two' }\r\n\t\u00a0\u00a0\u00a0 else { Write-Output 'three' }\r\n\t}\r\n<\/pre>\n<p>What is the output of this statement?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tf  \t25,true,'some string'<\/pre>\n<h4>Answer<\/h4>\n<pre>Processing...\r\n\tone\r\n<\/pre>\n<\/div>\n<p>The difficulty of this question depends on how much you automatically think in a conventional pro\u00c2\u00adgramming language. The function in question accepts three parameters, and we pass in three arguments, so clearly you should have<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a &lt;= 25\r\n$b &lt;= true\r\n$c &lt;= 'some string'\r\n<\/pre>\n<p>So for this statement&#8230;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f 25,true,'some string'<\/pre>\n<p>&#8230;the function should output &#8220;Processing&#8221; followed by &#8220;two&#8221;. That is, the first conditional should fail (<code>$b<\/code> is not null, the length of <code>$c<\/code> is not less than 5), and the second conditional should succeed (<code>$a<\/code> is an integer): \u00a0And yet, the actual answer is &#8220;Processing&#8221; followed by &#8220;one&#8221;.<\/p>\n<p>Consider this follow-up question: for the same function <code>f<\/code>, would this statement produce the same result or not?<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f(25,true,'some string') <\/pre>\n<p>That second question hints at what is relevant in both questions: how do you specify parameters to pass to a function? For this second question, you do not get the same result. You do not get &#8220;Processing&#8221; followed by &#8220;two&#8221;. Nor do you get &#8220;Processing&#8221; followed by &#8220;one&#8221;. In fact, you do not even get &#8220;Processing&#8221; followed by &#8220;three&#8221;. Because you never get &#8220;Processing&#8221; output at all! Instead, you get a runtime error.<\/p>\n<p>As the follow-up question illustrates, you can exacerbate your problem from the first question: here, your function never gets called at all; rather, you get a multitude of errors. The reason is that, unlike conventional languages, parentheses have nothing to do with calling a function! In PowerShell, parentheses are used to execute a command and then use the result of that command in place: But you have not given any valid PowerShell command to execute. Try just this-without the function <code>f <\/code>on the front-and you will see you get the same errors:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">(25,true,'some string')<\/pre>\n<h4>The Fix<\/h4>\n<p>The reason both of these function calls produce unexpected results is that you are not calling the function correctly. To associate the parameters as indicated&#8230;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">$a &lt;= 25\r\n$b &lt;= true\r\n$c &lt;= 'some string'\r\n<\/pre>\n<p>The function must be called with spaces rather than commas between arguments:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">f  25  true  'some string' <\/pre>\n<p class=\"quote\"><span class=\"style1\">&#8220;<\/span>Pass parameters the PowerShell<br \/> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 way: separate with spaces<span class=\"style1\">&#8220;<\/span><\/p>\n<p>When you use commas, you are creating a list of 3 elements that is then passed to parameter <code>$a<\/code>. You are passing nothing to parameters <code>$b<\/code> and <code>$c<\/code>, so they are both $null. Since <code>$b<\/code> is $null, the first conditional passes and you get &#8220;Processing&#8221; then &#8220;one&#8221;. Pass parameters the PowerShell way: separate with spaces<\/p>\n<div class=\"note\">\n<p class=\"note\"><i>Advanced note:<\/i> There are two right ways to call a PowerShell function and several wrong ways; you have seen two of the latter here. For an in-depth look at these, see <a href=\"https:\/\/www.simple-talk.com\/dotnet\/.net-tools\/down-the-rabbit-hole--a-study-in-powershell-pipelines,-functions,-and-parameters\/\">Down the Rabbit Hole: A Study in PowerShell Pipelines, Functions, and Parameters<\/a>.<\/p>\n<\/div>\n<h2>Conclusion<\/h2>\n<p>I hope on your way to the end here you had a few &#8220;Aha!&#8221; moments and gained a better understanding of assignments in PowerShell, both direct and across the function-calling boundary. Keep the highlighted principles in mind as you work in PowerShell and you will increase your productivity and reduce your head-scratching. \u00a0Of course, there are other areas of PowerShell use that could also cause consternation or frustration: But those are stories for another time&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PowerShell has some very valuable features, but it is a mistake to believe that all those skills that you&#8217;ve derived from more conventional programming languages will transfer over to PowerShell. There are some pitfalls for the unwary. Michael Sorens warns abut the most common PowerShell pitfalls and explains how to avoid them.&hellip;<\/p>\n","protected":false},"author":221868,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[35],"tags":[4635,4871],"coauthors":[6802],"class_list":["post-1976","post","type-post","status-publish","format-standard","hentry","category-powershell","tag-powershell","tag-sysadmin"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1976","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221868"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1976"}],"version-history":[{"count":10,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1976\/revisions"}],"predecessor-version":[{"id":69326,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1976\/revisions\/69326"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1976"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1976"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1976"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1976"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}