{"id":2052,"date":"2015-06-25T00:00:00","date_gmt":"2015-06-12T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/the-poster-of-the-plethora-of-powershell-pitfalls\/"},"modified":"2017-10-26T13:55:36","modified_gmt":"2017-10-26T13:55:36","slug":"the-poster-of-the-plethora-of-powershell-pitfalls","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/the-poster-of-the-plethora-of-powershell-pitfalls\/","title":{"rendered":"The Poster of the Plethora of PowerShell Pitfalls"},"content":{"rendered":"<ul class=\"series-articles\">\n<li>\n<p>A Plethora of PowerShell Pitfalls &#8211; Part 1: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\">Pesky Parameter Problems<\/a><\/p>\n<\/li>\n<li>\n<p>A Plethora of PowerShell Pitfalls &#8211; Part 2:\u00a0 <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\">A Portion of Potential Puzzles<\/a><\/p>\n<\/li>\n<li>\n<p>The Poster for a Plethora of PowerShell Pitfalls: Pretty Powerful Panaceas<\/p>\n<\/li>\n<\/ul>\n<p>Any programming language has elements of syntax or semantics that can lead to confusion, misunderstanding, or misdirection; and that leads to extra hours of head-scratching when trying to debug the inevitable issues that will crop up as a result. PowerShell is not immune to such issues, of course. Given that it is a relatively young language, though, its particular set of problem areas is perhaps less well known. Web searching can help you track down an issue, but sometimes it is not at all obvious what search term to use.<\/p>\n<p>This wallchart brings together most of the common pitfalls you are likely to encounter when tackling PowerShell. Most items provide a reference to get more information. You will find several major references oft quoted, along with a handful of individual blog posts mentioned here and there. Thanks to all those who have blogged about various PowerShell issues, and particular thanks to Roman Kuzmin for his <a href=\"https:\/\/github.com\/nightroman\/PowerShellTraps\">compendium of PowerShell Traps<\/a> and the folks at PowerShell.org who compiled the <a href=\"https:\/\/www.gitbook.com\/book\/devopscollective\/the-big-book-of-powershell-gotchas\"> Big Book of PowerShell Gotchas!<\/a><\/p>\n<h2>Contents<\/h2>\n<ul class=\"contents\">\n<li><a href=\"#first\">Selecting a string from an object is not a string<\/a><\/li>\n<li><a href=\"#second\">Interpolating object properties within a string does not work<\/a><\/li>\n<li><a href=\"#third\">Parameters are passed incorrectly to a function <\/a><\/li>\n<li><a href=\"#fourth\">Comparisons are not always commutative<\/a><\/li>\n<li><a href=\"#fifth\">Cmdlets return inconsistent results<\/a><\/li>\n<li><a href=\"#sixth\">Unable to pass arguments to external commands<\/a><\/li>\n<li><a href=\"#seventh\">Piping a hash table does not work<\/a><\/li>\n<li><a href=\"#eighth\">After filtering a hash table you no longer have a hash table<\/a><\/li>\n<li><a href=\"#ninth\">Functions return too much<\/a><\/li>\n<li><a href=\"#tenth\">Arithmetic operators produce unexpected results with arrays (precedence issue)<\/a><\/li>\n<li><a href=\"#eleventh\">Arithmetic operators produce unexpected results with arrays (operation issue)<\/a><\/li>\n<li><a href=\"#twelveth\">Zero is not always zero when using enums<\/a><\/li>\n<li><a href=\"#thirteenth\">Equality operators behave strangely with a list<\/a><\/li>\n<li><a href=\"#fourteenth\">An argument to a switch parameter is ignored<\/a><\/li>\n<li><a href=\"#fifteenth\">An empty string passed to an external application disappears<\/a><\/li>\n<li><a href=\"#sixteenth\">Omitting a $ on a variable reference might produce unexpected results rather than just an error<\/a><\/li>\n<li><a href=\"#seventeenth\">Re-importing a changed module does not work<\/a><\/li>\n<li><a href=\"#eighteenth\">Piping Format-Table into ConvertTo-xyz fails<\/a><\/li>\n<li><a href=\"#nineteenth\">Mixing Format-Table output amongst other output creates unexpected results<\/a><\/li>\n<li><a href=\"#twentieth\">Programs prompting for input hang in ISE<\/a><\/li>\n<li><a href=\"#twentiethandahalf\">The pipeline is not pipelining<\/a><\/li>\n<li><a href=\"#twentyfirst\">-contains seems broken; it only works on whole strings<\/a><\/li>\n<li><a href=\"#twentysecond\">PowerShell does not find known properties<\/a><\/li>\n<li><a href=\"#twentythird\">-Filter use is inconsistent across different cmdlets<\/a><\/li>\n<li><a href=\"#twentyfourth\">Code split across multiple lines does not always work<\/a><\/li>\n<li><a href=\"#twentyfifth\">Objects lose their types when you modify them<\/a><\/li>\n<li><a href=\"#twentysixth\">Variables in a script are inaccessible in the shell<\/a><\/li>\n<li><a href=\"#twentyseventh\">Serializing\/deserializing PS objects to XML loses some data types<\/a><\/li>\n<li><a href=\"#twentyeighth\">Imported CSV data are always strings<\/a><\/li>\n<li><a href=\"#twentyninth\">Switch statements do strange things<\/a><\/li>\n<li><a href=\"#thirtieth\">PowerShell does not always return a Count or Length property with strict mode<\/a><\/li>\n<li><a href=\"#thirtyfirst\">Invoking PowerShell.exe without specifying a version may invoke a newer PowerShell than that of the current host<\/a><\/li>\n<li><a href=\"#thirtysecond\">Invoking PowerShell.exe will launch the wrong version if the version parameter is not first<\/a><\/li>\n<li><a href=\"#thirtythird\">Relative script references in a script often fail<\/a><\/li>\n<li><a href=\"#thirtyfourth\">Dot notation for XML seems flaky<\/a><\/li>\n<li><a href=\"#thirtyfifth\">$null is a $null is a $null&#8230; not?<\/a><\/li>\n<li><a href=\"#thirtysixth\">PowerShell intermittently fails to enforce strong typing<\/a><\/li>\n<\/ul>\n<table>\n<tbody>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"first\">Selecting a string from an object is not a string<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Here we grab the C:\\temp directory and attempt to collect its name, but instead of showing &#8220;name is temp&#8221; you get this:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $myName = Get-ChildItem C:\\ -Filter temp | Select-Object \u2013Property name\r\nPS&gt; \"name is $myName\"\r\nname is @{Name=temp}\r\n<\/pre>\n<p>And you can confirm that you do not have a string:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $myName.GetType().FullName<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>PowerShell cmdlets return <i> objects<\/i> most of the time, rather than simple types (integers or strings). Select-Object is often used to do final selection, but it is designed to return objects-even when you ask for a <i>single<\/i> property. You have to tell it to just return the <i>value<\/i> of the property:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $myName = Get-ChildItem C:\\ -Filter temp | Select-Object \u2013ExpandProperty name\r\nPS&gt; \"name is $myName\"\r\nname is temp\r\n<\/pre>\n<p>Some cmdlets provide this as a built-in convenience so the above could be shortened:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $myName = Get-ChildItem C:\\ -Filter temp -Name<\/pre>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/www.gitbook.com\/book\/devops-collective-inc\/the-big-book-of-powershell-gotchas\/details\">Properties vs. Values<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"second\">Interpolating object properties within a string does not work<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>This example shows that instead of the value of the <code style=\"background-color: lightgrey;\">DisplayName<\/code> property of the <code style=\"background-color: lightgrey;\">$svc<\/code> variable you get the <i>type<\/i> of the <code style=\"background-color: lightgrey;\">$svc<\/code> variable and the property name &#8220;DisplayName&#8221; (I have truncated the output here for brevity):<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $svc = Get-Service -Name winrm\r\nPS&gt; \"svc is $svc.DisplayName\"\r\nsvc is ServiceController.DisplayName\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>PowerShell interpolates from a dollar sign ($) until the first character that is not a valid variable name character; in this case, a period. So, everything after the period is <i>just text<\/i> and is copied verbatim. The variable <code style=\"background-color: lightgrey;\">$svc<\/code> is an object, and interpolating it within a string yields its <i>type name<\/i> rather than its <i> contents<\/i>. But PowerShell can also interpolate expressions within a string-using the form <code style=\"background-color: lightgrey;\">$(expression)<\/code>-and that is the fix here:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $svc = Get-Service -Name winrm\r\nPS&gt; \u201csvc is $($svc.DisplayName)\u201d\r\nsvc is Windows Remote Management\r\n<\/pre>\n<p>Reference: Jeffrey Snover&#8217;s post <a href=\"http:\/\/blogs.msdn.com\/b\/powershell\/archive\/2006\/07\/15\/variable-expansion-in-strings-and-herestrings.aspx\"> Variable expansion in strings and here-strings<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"third\">Parameters are passed incorrectly to a function<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Calling a function with commas between arguments and\/or parentheses surrounding arguments fails, as with any of these attempts:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; func a,b,c\r\nPS&gt; func(a,b,c)\r\nPS&gt; func(a b c)\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Use <i>only<\/i> spaces between arguments-no parentheses and no commas:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; func a b c<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"fourth\">Comparisons are not always commutative<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>These two expressions are not the same:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $false -eq ''\r\nPS&gt; '' -eq $false\r\n<\/pre>\n<p>Reason: the right-hand operand is coerced to the type of the left-hand operand when comparing dissimilar types. So <code style=\"background-color: lightgrey;\">$false -eq ''<\/code> is <b> $true<\/b> because the empty string is false when coerced to a Boolean, but <code style=\"background-color: lightgrey;\">'' -eq $false<\/code> is <b>$false<\/b> because $false coerced to a string is &#8220;false&#8221;, which is obviously not an empty string.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Order your operands in a comparison with care so that you are actually testing what you intend to.<\/p>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"fifth\">Cmdlets return inconsistent results<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Yes, a cmdlet&#8217;s return type varies depending on whether it returns none, one, or more than one value from a function. That is inherent in the way cmdlets work-a cmdlet returns some number of objects nominally to be piped to something else. If it turns out it sent multiple objects, the type of the bunch taken together is an object array. But if it only returned one, it is just that object type.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>If a cmdlet potentially returns a stream of objects (an array), force it to always be an array for ease of handling, e.g.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $result = @(Some-Cmdlet x y z)<\/pre>\n<p>Also you have to force it on the <i> receiving<\/i> end.This&#8230;<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; function foo() { return @( 5 ) }\r\nPS&gt; $result = foo\r\n<\/pre>\n<p>\u00a0&#8230; does <i>not<\/i> return a list with one integer; it simply returns one integer. Instead do this:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; function foo() { return 5 }\r\nPS&gt; $result = @( foo )\r\n<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"sixth\">Unable to pass arguments to external commands<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>PowerShell interferes with some arguments being passed to an external command, e.g.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; echoargs c:\\tmp;c:\\other<\/pre>\n<p>Certain characters are special to PowerShell-here the semicolon is causing a problem.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Use quotes to suppress parsing of an argument, e.g.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; echoargs 'c:\\tmp;c:\\other'<\/pre>\n<p>\u00a0or use the verbatim parameter (<code style=\"background-color: lightgrey;\">--%<\/code>) to suppress all further processing on an line, e.g.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; echoargs --% c:\\tmp;c:\\other<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"seventh\">Piping a hash table does not work<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Piping a hash table sends it as a single object rather than as a stream of Key\/Value pairs. In this example, attempting to select the first key\/value pair actually returns the entire hash:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $hash = @{\"a\"=1;\"b\"=2;\"c\"='xyz' }\r\nPS&gt; $hash | Select -first 1\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Use the hash table&#8217;s <code style=\"background-color: lightgrey;\">GetEnumerator()<\/code> method to convert it to a pipeable collection.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $hash.GetEnumerator() | Select -First 1<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\"> PowerShell Pitfalls, Part 2<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"eighth\">After filtering a hash table you no longer have a hash table<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Building upon the last issue, you can filter a hash table&#8217;s entries like this:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $intHash = $hash.GetEnumerator() | where Value -is [int]<\/pre>\n<p>But you no longer have a hash table!<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>To filter a hash table and retain its type, use its <code style=\"background-color: lightgrey;\">GetEnumerator()<\/code> to feed to the pipeline, <i>then<\/i> reconvert to a hash table (with e.g. <code style=\"background-color: lightgrey;\">ConvertTo-HashTable<\/code> provided in the reference).<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $intHash = $hash.GetEnumerator() | where Value -is [int] | ConvertTo-HashTable<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\"> PowerShell Pitfalls, Part 2<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"ninth\">Functions return too much<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>A function returns <i>all<\/i> uncaptured output not just what you pass to a <code style=\"background-color: lightgrey;\">return<\/code> statement. This includes your own output from Write-Output calls as well as outputs from cmdlets you call.<\/p>\n<p>So this function to square a number will produce unexpected results:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">function square($x) {\r\n    Write-Output \"Squaring $x...\"\r\n    return $x * $x\r\n}\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>When writing a function to return a value use Write-Verbose or Write-Warning-rather than Write-Output-for console output. Also, ensure that you capture any output from each cmdlet you call.<\/p>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"tenth\">Arithmetic operators produce unexpected results with arrays (precedence issue)<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Simple arithmetic operations with an array seem wrong. For example, <code style=\"background-color: lightgrey;\">1,2 * 3<\/code> does not return a 2 element list containing 1 and 6. It is really <code style=\"background-color: lightgrey;\">(1,2) * 3<\/code> so it returns a 6-element list: 1,2,1,2,1,2.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Comma has higher precedence than arithmetic operators! Use parentheses to override operator precedence.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; 1, (2 * 3)<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"eleventh\">Arithmetic operators produce unexpected results with arrays (operation issue)<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Applying arithmetic operators to a list operates on the list as a whole, not on individual elements of the list so, e.g. <code style=\"background-color: lightgrey;\">(1,2) * 3<\/code> turns a 2-element list into a 6-element list, rather than multiplying each element by 3.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>To map an arithmetic (or other) operation to each element of a list do it with a loop:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; 1, 2 | ForEach { $_ * 3 }<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twelveth\">Zero is not always zero when using enums<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Here we use the known enum ConsoleColor whose Black element happens to map to 0. The equality comparison is commutative: enum coerced to int is 0; int coerced to enum is Black.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $object = [ConsoleColor]::Black\r\nPS&gt; if (0 -eq $object) { 'Yes!' }\r\nPS&gt; if ($object -eq 0) { 'Yes!' }\r\n<\/pre>\n<p>But a conditional that evaluates to $false-like 0-should be skipped!<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; if (0) { 'this will not appear' }\r\nPS&gt; if ($object) { 'this appears!' }\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Be wary when testing the truth-value of an <i> object<\/i> (as opposed to a Boolean predicate). Zero is $false, empty string is $false, and an empty array is $false, but any other object-even when effectively empty-is $true.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $object = [ConsoleColor]::Black\r\nPS&gt; if ($object) { 'yes!' }\r\nPS&gt; $object = @{} # empty hash table\r\nPS&gt; if ($object) { 'yes!' }\r\nPS&gt; $object = [PSCustomObject] {} # empty custom object\r\nPS&gt; if ($object) { 'yes!' }\r\n<\/pre>\n<p>Reference: PowerShell Traps, <a href=\"https:\/\/github.com\/nightroman\/PowerShellTraps\/tree\/master\/Basic\/Enums-evaluated-to-true\">Enums-are-always-evaluated-to-true<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirteenth\">Equality operators behave strangely with a list<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>This both looks like the object is equal and unequal to 1 at the same time!<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $obj = 1, $null, 2, 'abc', 3\r\nPS&gt; if ($obj -eq 1) { 'yes!' }\r\nyes!\r\nPS&gt; if ($obj -ne 1) { 'yes!' }\r\nyes!\r\n<\/pre>\n<p>This is particularly pernicious when looking for $null:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; if ($obj -eq $null) { 'got here!' }\r\ngot here!\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>In reality, the equality operators act as filters, a rather obscure feature; there is one item that is &#8216;1&#8217; and 4 items that are not &#8216;1&#8217;:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $obj = 1, $null, 2, 'abc', 3\r\nPS&gt; $eqResult = $obj -eq 1\r\nPS&gt; $neResult = $obj -ne 1\r\nPS&gt; $eqResult.Count\r\n1\r\nPS&gt; $neResult.Count\r\n4\r\n<\/pre>\n<p>This is again a variation on the type coercion between dissimilarly typed operands, as evinced by reversing them. Here you get intuitive results: the list is not equal to the integer 1:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; if (1 -eq $obj) { 'yes!' } else {'no'}\r\nno\r\nPS&gt; if (1 -ne $obj) { 'yes!' } else {'no'}\r\nyes!\r\n<\/pre>\n<p>Reference: PowerShell Traps, looks-like-object-is-null<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"fourteenth\">An argument to a switch parameter is ignored<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Typically you pass a parameter <i>name<\/i> a value of <i>value<\/i> with <code style=\"background-color: lightgrey;\">-name value<\/code>. But with a switch parameter that does not work. Consider this function:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">function f([switch]$negate)\r\n{ if ($negate) { -42 } else { 42 } }\r\n<\/pre>\n<p>PowerShell ignores the seeming assignment of $negate to $false:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; f -negate $false\r\n-42\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Switch parameters do <i>not<\/i> take arguments, so you must set the switch with any of these variations:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; My-Cmdlet \u2013Force\r\nPS&gt; My-Cmdlet -Force:$false\r\nPS&gt; My-Cmdlet -Force:$true\r\n<\/pre>\n<p>rather than, e.g.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; My-Cmdlet -Force $false<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls\/\"> PowerShell Pitfalls, Part 1<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"fifteenth\">An empty string passed to an external application disappears<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>This command, for example, passes 2 arguments, not 3, to the PowerShell Community Extensions utility program echoargs:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; echoargs \"a\" \"\" \"b\"<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Use the verbatim parameter (<code style=\"background-color: lightgrey;\">--%<\/code>) or use an escaped quoted value (<code>`\"x`\"<\/code>) or (<code>`\"$var`\"<\/code>), e.g.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; echoargs --% \"a\" \"\" \"b\"<\/pre>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\"> PowerShell Pitfalls, Part 2<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"sixteenth\">Omitting a $ on a variable reference might produce unexpected results rather than just an error<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>In this example, &#8220;a&#8221; without a preceding dollar-sign is happily accepted as just a string constant so there is no error and you get a different result.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $a = \"b\"\r\nPS&gt; $list = \"a\",\"b\",\"c\"\r\nPS&gt; $list | Select-String a\r\na\r\nPS&gt; $list | Select-String $a\r\nb\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>None really; use code reviews and unit tests<\/p>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\"> PowerShell Pitfalls, Part 2<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"seventeenth\">Re-importing a changed module does not work<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>After modifying code in a module, just doing <code style=\"background-color: lightgrey;\">Import-Module x <\/code> again does <b> <i>not<\/i><\/b> find your code changes if you have previously loaded the module in your current session.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Import-Module silently ignores your requests to reload unless you force it to: use <code style=\"background-color: lightgrey;\">Import-Module -Force<\/code> to load your modified code. Alternately, you could unload the module then import again if you prefer.<\/p>\n<p>Reference: <a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/a-plethora-of-powershell-pitfalls-part-2\/\"> PowerShell Pitfalls, Part 2<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"eighteenth\">Piping Format-Table into ConvertTo-xyz fails<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Say you created some useful output&#8230;<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; ps | Select -first 10 | Format-Table<\/pre>\n<p>And you want to pipe that nicely formatted result into ConvertTo-Html or\u00a0 or ConvertTo-Csv (or Export-Csv), etc. Space precludes sample output, but try this and you will see that the output is quite different from above:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; ps | Select -first 10 | Format-Table | ConvertTo-Csv<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Avoid using Format-Table except at the end of a pipe. Format-Table outputs formatting codes for display, which makes its output unsuitable for piping to other cmdlets in general. (Though you can safely pipe Format-Table to a few select cmdlets like Out-File and Out-String.)<\/p>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/devops-collective-inc.gitbooks.io\/the-big-book-of-powershell-gotchas\/content\/manuscript\/format-right.html\">Format Right<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"nineteenth\">Mixing Format-Table output amongst other output creates unexpected results<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Consider this series of four commands (aliases used for brevity) output to the console:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; gps idle; gps system; @{a=0}; gsv winrm; gps idle<\/pre>\n<p>PowerShell begins outputting objects from Get-Process (alias gps) in table format, then encounters two commands that generate <i>other<\/i> kinds of output so just outputs those in list format, and resumes outputting process objects with the last command.<\/p>\n<p>Now, just add a Format-Table (alias ft) in the middle. (This is quite different from the prior ft issue; this ft is correctly at the end of a pipe.)<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; gps idle; gps system; @{a=0} | ft; gsv winrm; gps idle<\/pre>\n<p>The output is different not just for the third command that we changed, but for the remaining commands as well!<\/p>\n<p>(With thanks to &#8220;Mike Z&#8221; in this <a href=\"http:\/\/stackoverflow.com\/a\/29333113\/115690\"> StackOverflow post<\/a>.)<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Fomat-Table (alias ft) apparently resets the object type that PowerShell thinks is current. So the Get-Service (alias gsv) sets a new object type as the current one, and it is output as a table. Now, when it runs gps again it is not the current object type so that is now output in list format.<\/p>\n<p>The workaround is simple: Format-Table should only ever be used as a terminal command-do not sandwich it in the middle of a sequence of like objects.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentieth\">Programs prompting for input hang in ISE<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>A C# program (or other external application) asking for input runs fine in a &#8220;plain&#8221; PowerShell window but hangs in PowerShell ISE.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Likely the C# code implementing the PS cmdlet uses <code style=\"background-color: lightgrey;\">Console.ReadLine()<\/code> which is not supported in PowerShell ISE. Revise the program to use <code style=\"background-color: lightgrey;\">Host.UI.ReadLine()<\/code> instead, which will work in <i>either<\/i> PowerShell ISE or the regular PowerShell window.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentiethandahalf\">The pipeline is not pipelining<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>The PowerShell pipeline is supposed to (more or less) pump each object down the pipeline from one function to the next as soon as it is ready. Some homespun functions do not send data along the pipeline until it processes all its inputs. For example, this code looks fine in isolation but if you pipe it to something else, its data shows up all at once at the end:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">function f ([ string []] $data )\r\n{\r\n  $out = @()\r\n  foreach ( $s in $data) {\r\n    start-sleep 2; $out += $s }\r\n  Write-Output $out\r\n}\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>You need to adapt your style for writing pipelineable code: rather than accumulate output internally, just output it as it goes. In other words, let PowerShell accumulate it for you.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">function f ([ string []] $data )\r\n{\r\n  foreach ( $s in $data) {\r\n    start-sleep 2; Write-Output $s }\r\n}\r\n<\/pre>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/devops-collective-inc.gitbooks.io\/the-big-book-of-powershell-gotchas\/content\/manuscript\/accumulating-output-in-a-function.html\">Accumulating Output in a Function<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentyfirst\">-contains seems broken; it only works on whole strings<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>With notepad running, this finds it with a whole name:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Process | Where Name -contains 'notepad'<\/pre>\n<p>But attempting to use a substring like this fails:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Process | Where Name -contains 'note'<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>The <code style=\"background-color: lightgrey;\">-contains<\/code> operator does <i>not<\/i> do operations against a string; it <i> only<\/i> operates on a list. That is, it answers the question &#8220;does this list contain a given element?&#8221; To check for a whole or partial string match use <code style=\"background-color: lightgrey;\">-like<\/code> or <code style=\"background-color: lightgrey;\">-match<\/code>.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Process | Where Name -match 'note'\r\nPS&gt; Get-Process | Where Name -like '*note*'\r\n<\/pre>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/devops-collective-inc.gitbooks.io\/the-big-book-of-powershell-gotchas\/content\/manuscript\/contains-isnt-like.html\">-Contains isn&#8217;t -Like<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentysecond\">PowerShell does not find known properties<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Here you select some properties about services and want to display just the running services, but it either returns nothing (strict mode <i>off<\/i>) or causes an error (strict mode <i>on<\/i>).<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Service | Select Name, DisplayName | Where Status -eq Running<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>The order of pipeline statements matters. After the Select, only two properties exist-there is no <code style=\"background-color: lightgrey;\">Status<\/code> property anymore! Do the Where before the Select:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Service |\r\nWhere Status -eq Running | Select Name,DisplayName\r\n<\/pre>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/devops-collective-inc.gitbooks.io\/the-big-book-of-powershell-gotchas\/content\/manuscript\/you-cant-have-what-you-dont-have.html\">You Can&#8217;t Have What You Don&#8217;t Have<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentythird\">-Filter use is inconsistent across different cmdlets<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Consider these examples, showing that <code style=\"background-color: lightgrey;\">-filter<\/code> needs a glob-pattern, a Boolean predicate with &#8216;=&#8217;, and a Boolean predicate wrapped in a block using &#8216;-eq&#8217;, respectively:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-ChildItem -Filter *.html\r\nPS&gt; Get-WmiObject -Class Win32_LogicalDisk\r\n-Filter \"DriveType=3\"\r\nPS&gt; Get-ADUser \u2013Filter { title -eq 'CTO' }\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>That&#8217;s not PowerShell&#8217;s fault; it just passes along the parameter value to the underlying provider (the file system, WMI, or ActiveDirectory). And those technologies have long ago created their varying syntaxes for a filter. Sadly, the workaround is to read the documentation to see what you need.<\/p>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/devops-collective-inc.gitbooks.io\/the-big-book-of-powershell-gotchas\/content\/manuscript\/filter-values-diversity.html\">-Filter Values Diversity<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentyfourth\">Code split across multiple lines does not always work<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>If you copy\/paste this-don&#8217;t type it in!-it will fail:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Service -name win* ` \r\n    -exclude winrm `\r\n    -DependentServices\r\n<\/pre>\n<p>All whitespace is not created equal in PowerShell. Line breaks <i>can<\/i> be added with impunity after certain characters ( <code style=\"background-color: lightgrey;\">| , . :: ; ( [ { =<\/code> ). But you can forcibly add a line break anywhere else by preceding with a back tick as above. The problem is that if there is a space after any of those backticks (like there is in the first line), the code breaks!<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Use different patterns to avoid backticks whenever possible. Here, create a hash table of the cmdlet arguments (note that the switch parameter accepts either a $true or $false value) where you can add line breaks between expressions <i>without<\/i> backticks:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $params = @{\r\n    name = 'win*'\r\n    exclude = 'winrm'\r\n    DependentServices = $false\r\n}\r\n<\/pre>\n<p>then splat that hash table into arguments for the cmdlet, all with <i>no<\/i> backticks:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Service @params<\/pre>\n<p>Reference: PowerShell Gotchas, <a href=\"https:\/\/www.gitbook.com\/book\/devops-collective-inc\/the-big-book-of-powershell-gotchas\/details\">Backtick, Grave Accent, Escape<\/a><\/p>\n<p>Reference: Scripting Guy, <a href=\"http:\/\/bit.ly\/1JOADty\"> http:\/\/bit.ly\/1JOADty<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentyfifth\">Objects lose their types when you modify them<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>In PowerShell it is easy to create a strongly-typed array:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $array = [Int[]](1,2,3,4,5)\r\nPS&gt; $array.GetType().FullName\r\nSystem.Int32[]\r\n<\/pre>\n<p>But, like <a href=\"https:\/\/en.wikipedia.org\/wiki\/Uncertainty_principle\"> Heisenberg&#8217;s principle<\/a> states, touching that data causes the type to change! Here we just add a new element to the array and now they are all vanilla Objects:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $array += 6\r\nPS&gt; $array.GetType().FullName\r\nSystem.Object[]\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>The fix for those, though unexpected, is to strongly type the <i>variable<\/i> directly rather than the <i>data<\/i> assigned to it, and it will retain its typing:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; [Int[]]$array = 1,2,3,4,5\r\nPS&gt; $array.GetType().FullName\r\nSystem.Int32[]\r\nPS&gt; $array += 6\r\nPS&gt; $array.GetType().FullName\r\nSystem.Int32[]\r\n<\/pre>\n<p>Reference: <a href=\"http:\/\/powershell.com\/cs\/blogs\/tips\/archive\/2010\/11\/11\/strongly-typed-arrays.aspx\"> Strongly Typed Arrays<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentysixth\">Variables in a script are inaccessible in the shell<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Say, for example you have trial.ps1 containing just this:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">$someVariable = 123.45\r\n\"value is $someVariable\"\r\n<\/pre>\n<p>Run the script then try to display the variable again, but either it does not exist (strict mode <i>off<\/i>) or it will cause an error (strict mode <i>on<\/i>):<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; C:\\temp\\trial.ps1\r\nvalue is 123.45\r\nPS&gt; \u201cnow value is $someVariable\u201d\r\nnow value is\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>By just invoking a script you are running everything in a subshell, a <i>child scope<\/i> to your current scope. Once the script finishes that child scope goes away; it does not affect the current scope at all. To invoke a script in the <i>current<\/i> scope, you must <i>dot-source<\/i> it, which is simply a dot followed by a space and the name of your source file.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; . C:\\temp\\trial.ps1\r\nPS&gt; \u201cnow value is $someVariable\u201d\r\nvalue is 123.45\r\nnow value is 123.45\r\n<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentyseventh\">Serializing\/deserializing PS objects to XML loses some data types<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Create some data, export it, then re-import it:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">$t1 = @{ myData = 11, 22, 33 }\r\n$t1 | Export-Clixml temp.clixml\r\n$t2 = Import-Clixml temp.clixml\r\n<\/pre>\n<p>Now examine the data types of the myData property:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">                    $t1.myData.GetType().Name # Object[]\r\n$t2.myData.GetType().Name # ArrayList\r\n<\/pre>\n<p>A second example:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">                   $t1 = [ordered]@{ p1=11;p2=22;p3=33 }\r\n$t1 | Export-Clixml temp.clixml\r\n$t2 = Import-Clixml temp.clixml\r\n$t1.GetType().Name #OrderedDictionary\r\n$t2.GetType().Name #Hashtable\r\n<\/pre>\n<p>Certain types are preserved, i.e. those integers above remain real integers. Likewise with other simple types, but not with complex ones.<\/p>\n<p>For example add another property inside $t1:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">$t1 = @{ \r\n    myData = 11, 22, 33\r\n    svcs = Get-Service\r\n}\r\n<\/pre>\n<p>And the type of the elements within svcs changes from <code style=\"background-color: lightgrey;\">ServiceController<\/code> to <code style=\"background-color: lightgrey;\">PSObject<\/code>.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>No simple fix. If datatype matters, you will need to explicitly correct the objects in your code.<\/p>\n<p>Reference: PowerShell Traps, Array-becomes-ArrayList<\/p>\n<p>Reference: PowerShell Traps, <a href=\"https:\/\/github.com\/nightroman\/PowerShellTraps\/tree\/master\/Clixml\/OrderedDictionary-becomes-Hashtable\"> OrderedDictionary-becomes-Hashtable<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentyeighth\">Imported CSV data are always strings<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>This is easy to forget, because using data <i>within<\/i> PowerShell you get used to strong-typing. This will sort by the number of seconds of cpu time as a decimal value:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Process | Select ProcessName,CPU | Sort CPU<\/pre>\n<p>But if you read the values from a CSV file, for example, you only have strings. This just sorts lexicographically:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Process | Select ProcessName,CPU | Export-Csv data.csv\r\nPS&gt; Import-Csv data.csv | Sort CPU\r\n<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>To import data with strong typing, generate a series of <code style=\"background-color: lightgrey;\">PSCustomObjects<\/code> with explicit type casting on appropriate elements:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; Get-Process | Select ProcessName,CPU |\r\nExport-Csv data.csv\r\nPS&gt; Import-Csv data.csv | \r\nForEach {\r\n    [PSCustomObject] @{\r\n        Time = [double]$_.CPU;\r\n        Name = $_.ProcessName;\r\n    }} |\r\nSort Time\r\n<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"twentyninth\">Switch statements do strange things<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Like many languages, <code style=\"background-color: lightgrey;\">switch<\/code> is an alternate to a series of multiple <code style=\"background-color: lightgrey;\">if<\/code> statements. But in PowerShell, <code style=\"background-color: lightgrey;\">switch<\/code> is also a looping construct; it can operate on a collection.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>* <code style=\"background-color: lightgrey;\">break<\/code> and <code style=\"background-color: lightgrey;\">continue<\/code> inside a <code style=\"background-color: lightgrey;\">switch<\/code> block work <i>for the switch<\/i>, not any containing loop, as is more common with other languages.<\/p>\n<p>* a <code style=\"background-color: lightgrey;\">switch<\/code> inside a script block introduces its own context for <code style=\"background-color: lightgrey;\">$_<\/code>, hiding any such value from an outer block.<\/p>\n<p>* <code style=\"background-color: lightgrey;\">break<\/code> works like you would expect when using <code style=\"background-color: lightgrey;\">switch<\/code> on a single value, but when used on a collection it stops the whole loop.<\/p>\n<p>Space prohibits detailed examples of all these; see the reference.<\/p>\n<p>Reference: PowerShell Traps, <a href=\"https:\/\/github.com\/nightroman\/PowerShellTraps\/blob\/master\/Basic\/Switch-is-a-looping-construct\"> Switch-is-a-looping-construct<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtieth\">PowerShell does not always return a Count or Length property with strict mode<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>As a convenience, PowerShell V3 introduced the Count or Length pseudo-property for scalar objects the way it has always been available for arrays. This lets you check the cardinality of a returned collection for 1 as easily as you could for more than 1 without requiring extra code. This pseudo-property works fine with strict mode disabled, but when enabled it causes an error:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">                   PS&gt; Set-StrictMode -Version Latest\r\nPS&gt; $array = 1..5; $array.Count\r\n5\r\nPS&gt; $item = 25; $item.Count\r\nThe property 'Count' cannot be found on this object.<\/pre>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>PowerShell tries to prevent scripting errors by allowing you to query the Count or Length property even on a single object. And this works fine if strict mode is disabled. But, alas, it causes an error with strict mode enabled. You must still apply extra code for special casing under such circumstances:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $item = 25\r\nPS&gt; $returnCount = if ($item -is [array]) { $item.Count } elseif ($item) { 1 } else { 0 }\r\n<\/pre>\n<p>Reference: about_Properties (Properties of Scalar Objects and Collections)<\/p>\n<p><a href=\"https:\/\/connect.microsoft.com\/PowerShell\/feedback\/details\/770111\/set-strictmode-fails-on-the-quasi-property-count-for-scalars-and-invalidates-its-usefulness\"> Microsoft Connect<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtyfirst\">Invoking PowerShell.exe without specifying a version may invoke a newer PowerShell than that of the current host<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Assuming you are in a version 3 or greater PowerShell, switch to version 2 PowerShell as a starting point:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; powershell -version 2 -noprofile<\/pre>\n<p>Now invoke powershell.exe without a version and just print its version:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; powershell -noprofile '$PSVersionTable.PSVersion.ToString()'<\/pre>\n<p>That will print 3.0 (or whatever your latest version is) rather than 2.0.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>If you are in a given version and want a subshell of the same version, specify that version explicitly when invoking powershell.exe:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; powershell -version 2 -noprofile '$PSVersionTable.PSVersion.ToString()'<\/pre>\n<p>Reference: PowerShell Traps, <a href=\"https:\/\/github.com\/nightroman\/PowerShellTraps\/tree\/master\/PowerShell.exe\/Not-current-version\"> Unwanted-version<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtysecond\">Invoking PowerShell.exe will launch the wrong version if the version parameter is not first<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Nothing prevents attempting to launch a subshell with a specific version of PowerShell using either of these:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; PowerShell -Version 2 -NoProfile \r\nPS&gt; PowerShell -NoProfile -Version 2 \r\n<\/pre>\n<p>However, they produce different results!<\/p>\n<p>Assuming you are in a version 3 shell or later, the first command will correctly run a version 2 shell, while the second will ignore that parameter, running the same version you started in.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>Normally named parameters are order-independent but for some reason that is not the case here. The workaround is straightforward: make sure the <code style=\"background-color: lightgrey;\">-Version<\/code> parameter is first.<\/p>\n<p>Reference: PowerShell Traps, <a href=\"https:\/\/github.com\/nightroman\/PowerShellTraps\/tree\/master\/PowerShell.exe\/Version-parameter\"> Version-must-be-first<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtythird\">Relative script references in a script often fail<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Dot-sourcing a file inside a script using a relative path fetches the file relative to your current directory-<i>not<\/i> the directory where the script resides. For example, put this into script1.ps1 in directory A:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">. .\\script2.ps1\r\nGet-MyMessage\r\n<\/pre>\n<p>And put this into script2.ps1 in the same directory:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">function Get-MyMessage() { 'hello' }<\/pre>\n<p>The first script will run fine <i>only<\/i> if you are in the same directory when you run it. Set your location to a different location, directory B, and attempt to run the first script.<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; A\\script1.ps1<\/pre>\n<p>It should fail saying it could find neither script2.ps1 nor Get-MyMessage.<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>To make a script use a path relative to itself rather than your current directory, use <code style=\"background-color: lightgrey;\">$PSScriptRoot<\/code>. The script1.ps1 file should thus contain:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">. $PSScriptRoot\\script2.ps1\r\nGet-MyMessage\r\n<\/pre>\n<p>Then the script should run successfully.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtyfourth\">Dot notation for XML seems flaky<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>PowerShell&#8217;s dynamic object support for XML is powerful but can sometimes lie to you. Consider this XML:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $xml = [xml]'&lt;Root&gt;&lt;Child \/&gt;&lt;Child \/&gt;&lt;\/Root&gt;'\r\nPS&gt; @($xml.SelectNodes(\"\/Root\/Child\")) .Count\r\n2\r\nPS&gt; @($xml.Root.Child).Count\r\n2\r\n<\/pre>\n<p>Using both an XPath accessor and a dynamic object accessor (popularly called &#8220;dot notation&#8221;) you get back an accurate count of &lt;Child&gt; elements. But not so here:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; $xml = [xml]'&lt;Root&gt;&lt;\/Root&gt;'\r\nPS&gt; @($xml.SelectNodes(\"\/Root\/Child\")). Count\r\n0\r\nPS&gt; @($xml.Root.Child).Count\r\n1\r\n<\/pre>\n<p>XPath says correctly that there are no such children; dot notation says there is one child! (That assumes you have strict mode disabled; with strict mode enabled the last line will instead generate an error. (With thanks to Nick in this <a href=\"http:\/\/stackoverflow.com\/a\/923739\/115690\"> StackOverflow post<\/a>.)<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>The issue here has nothing to do with XML per se. Rather, it is a peculiarity of PowerShell&#8217;s dynamic object support, whatever the source: you get a <code style=\"background-color: lightgrey;\">$null<\/code> whenever a property in the chain is missing. Here we get <code style=\"background-color: lightgrey;\">$xml.Root.Child<\/code> being <code style=\"background-color: lightgrey;\">$null<\/code>, but you would also get <code style=\"background-color: lightgrey;\">$null<\/code> for, e.g. <code style=\"background-color: lightgrey;\">$xml.Root.Child.Other.Nonexistent.Node<\/code>. That sounds eminently reasonable and, in fact, was a specific design decision (according to Bruce Payette in a response to <a href=\"http:\/\/www.winterdom.com\/2009\/03\/06\/powershellandnullvalues.html\">this post<\/a>). Bruce goes on to suggest that in scripts you should always enable strict mode in which case you would get an error, rather than a <code style=\"background-color: lightgrey;\">$null<\/code>.<\/p>\n<p>But with strict mode disabled, you do have a <code style=\"background-color: lightgrey;\">$null<\/code>, so let&#8217;s see what happens to it. Before applying the Count property, we wrap it with <code style=\"background-color: lightgrey;\">@()<\/code> to force the results to an array. That way, presumably whether you got back none, one, or many elements, it would always be an array (as described in an earlier pitfall). But here you are <i>not<\/i> getting &#8220;none&#8221;-you are getting a <code style=\"background-color: lightgrey;\">$null<\/code>. And <code style=\"background-color: lightgrey;\">@($null)<\/code> is in fact, an array of one element, that element being a <code style=\"background-color: lightgrey;\">$null<\/code>.<\/p>\n<p>The workaround is to turn <code style=\"background-color: lightgrey;\">$null<\/code> into none when appropriate:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">@($xml.Root.Child | Where { $_ }).Count<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtyfifth\">$null is a $null is a $null&#8230; not?<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>Consider these functions <code style=\"background-color: lightgrey;\">foo<\/code> and <code style=\"background-color: lightgrey;\">bar<\/code> which both apparently return <code style=\"background-color: lightgrey;\">$null<\/code>:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; function foo() { $null }\r\nPS&gt; function bar() { }\r\nPS&gt; (foo) -eq $null\r\nTrue\r\nPS&gt; (bar) -eq $null\r\nTrue\r\n<\/pre>\n<p>But now compare what happens when you feed each of those into a pipe:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; foo | %{ \"this prints\" }\r\nthis prints\r\nPS&gt; bar | %{ \"this does not print!\" }\r\n# PRINTS NOTHING\r\n<\/pre>\n<p>(With thanks to&#8221;alex2k8&#8243; in this <a href=\"http:\/\/stackoverflow.com\/a\/804386\/115690\"> StackOverflow post<\/a>.)<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>This is another manifestation of the <code style=\"background-color: lightgrey;\">$null<\/code> vs none conundrum mentioned above. The function <code style=\"background-color: lightgrey;\">foo()<\/code> returned something, a single object, that happens to be <code style=\"background-color: lightgrey;\">$null<\/code>. You can certainly feed any single object into a pipe, even a null. The <code style=\"background-color: lightgrey;\">bar()<\/code> function, on the other hand returned nothing, not even a <code style=\"background-color: lightgrey;\">$null<\/code>, so there is nothing to feed into the pipeline!<\/p>\n<p>There is no specific workaround here, only to be cognizant that when you expect a return value from a function, make sure that function returns something-your functions will not be as blatantly obvious as the <code style=\"background-color: lightgrey;\">bar()<\/code> function here!<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\n<h3 id=\"thirtysixth\">PowerShell intermittently fails to enforce strong typing<\/h3>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"50%\">\n<p><strong>Issue:<\/strong><\/p>\n<p>You can specify types for function parameters to demand that PowerShell check those parameters:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">PS&gt; function f([int]$a, [bool]$b, [string]$c) { \"$a, $b, &lt;$c&gt;\" }<\/pre>\n<p>Then <code style=\"background-color: lightgrey;\">f -a 25<\/code> will work fine while <code style=\"background-color: lightgrey;\">f -a xyz<\/code> will report &#8220;Cannot convert value &#8216;xyz&#8217; to type &#8216;System.Int32&#8217;.&#8221; Great; it does strong type checking! Well, it would more accurately be called strong-unless-a-suitable-conversion-exists type checking. So <code style=\"background-color: lightgrey;\">f -b xyz<\/code> is rejected as not a Boolean, but <code style=\"background-color: lightgrey;\">f -b 1<\/code> succeeds, converting 1 to $true. (Ironically <code style=\"background-color: lightgrey;\">f -b<\/code> <code style=\"background-color: lightgrey;\">true<\/code> is rejected-that&#8217;s just text like xyz-you must use <code style=\"background-color: lightgrey;\">f -b $true<\/code> to pass a Boolean.) Worse yet,\u00a0 <code style=\"background-color: lightgrey;\">f -a 5.42<\/code> succeeds, but <code style=\"background-color: lightgrey;\">$a<\/code> is just 5 after being converted to an integer! And <i>any<\/i> object has a ToString() method so anything can be passed into parameter <code style=\"background-color: lightgrey;\">$c<\/code>, e.g. <code style=\"background-color: lightgrey;\">f -c (get-process svchost)<\/code> runs without complaint but gives ugly output. (With thanks to Richard Berg in this <a href=\"http:\/\/stackoverflow.com\/a\/837229\/115690\"> StackOverflow post<\/a>.)<\/p>\n<\/td>\n<td width=\"50%\">\n<p><strong>Workaround:<\/strong><\/p>\n<p>To avoid unexpected arguments being auto-converted, you have to do your type-checking manually. You might get by with something like this which omits the type specifier on each parameter completely and does type checking in the body:<\/p>\n<pre class=\"crayon:false\" style=\"background-color: lightgrey; font-size: 0.75em; line-height: 12pt;\">function f($a, $b, $c) {\r\n    if ($a -and $a -isnot [int]) { throw 'not an int' }\r\n    if ($b -and $b -isnot [bool]) { throw 'not a bool' }\r\n    if ($c -and $c -isnot [string]) { throw 'not a string' }\r\n    \"$a, $b, &lt;$c&gt;\"\r\n}\r\n<\/pre>\n<p>Then <code style=\"background-color: lightgrey;\">f -b 1<\/code>, for example, would be rejected, as would <code style=\"background-color: lightgrey;\">f -a 5.42<\/code> and <code style=\"background-color: lightgrey;\">f -c (get-process svchost)<\/code>. Alas, that would still falter on certain degenerate cases. <code style=\"background-color: lightgrey;\">f -b \"\"<\/code>, for example, arguably should be rejected but it is not.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Yes, there <i>are<\/i> other pitfalls out there that did not make it on this list! There are two possible reasons why:<\/p>\n<ol>\n<li>\n<p>Deliberate omission due to too convoluted, arcane, or peculiar. Perhaps an issue might affect just five people out there. Sorry if you are one of those five! But I needed to focus on what would affect-and thus interest-the most people.<\/p>\n<\/li>\n<li>\n<p>Inadvertent omission because I never got snared by it and\/or I missed it in my research for this article.<\/p>\n<\/li>\n<\/ol>\n<p>If you know of a pitfall that might affect many people, then by all means share it in a comment below!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the downsides of learning a new computer language is that transfer of training doesn&#8217;t always work to your advantage. In fact, the habits you picked up in the past may now cause confusion. In this poster or wall-chart for long walls, Michael Sorens selects the thirty-six most common causes of confusion for anyone getting to grips with PowerShell. Forewarned is forearmed.&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":[4178,4635,4871],"coauthors":[6802],"class_list":["post-2052","post","type-post","status-publish","format-standard","hentry","category-powershell","tag-bi","tag-powershell","tag-sysadmin"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2052","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=2052"}],"version-history":[{"count":24,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2052\/revisions"}],"predecessor-version":[{"id":75058,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2052\/revisions\/75058"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=2052"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=2052"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=2052"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=2052"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}