{"id":254,"date":"2014-12-03T00:01:00","date_gmt":"2014-12-03T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/12\/03\/enforce-better-script-practices-by-using-set-strictmode\/"},"modified":"2019-02-18T10:36:47","modified_gmt":"2019-02-18T17:36:47","slug":"enforce-better-script-practices-by-using-set-strictmode","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/enforce-better-script-practices-by-using-set-strictmode\/","title":{"rendered":"Enforce Better Script Practices by Using Set-StrictMode"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Boe Prox shows how to use <\/span><b style=\"font-size:12px\">Set-StrictMode<\/b><span style=\"font-size:12px\"> to write better scripts.<\/span>\nHonorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the third part in a series of five posts about troubleshooting Windows PowerShell scripts and functions. The series includes:<\/p>\n<ol>\n<li><a href=\"http:\/\/blogs.technet.comhttps:\/\/devblogs.microsoft.com\/scripting\/provide-support-using-verbose-and-debug-streams\/\" target=\"_blank\">Provide Support by Using Verbose and Debug Streams<\/a><\/li>\n<li><a href=\"http:\/\/blogs.technet.comhttps:\/\/devblogs.microsoft.com\/scripting\/troubleshoot-by-using-set-psdebug\/\" target=\"_blank\">Troubleshoot by Using Set-PSDebug<\/a><\/li>\n<li><b>Enforce Better Script Practices by Using Set-StrictMode<\/b> (this post)<\/li>\n<li>Trace Your Commands by Using Trace-Command<\/li>\n<li>Use the PowerShell Debugger<\/li>\n<\/ol>\n<p>If you remember back in the VBScript days, if you wanted to enforce better practices with the handling of undeclared variables in your code, you would use <b>Option Explicit<\/b>. If you tried to throw in a variable that wasn&rsquo;t defined at the top of the script, it would throw an error message and stop executing. Well, we&rsquo;ve come further along with Windows PowerShell.\nBy using the <b>Set-StrictMode<\/b> cmdlet, we can enforce some common &ldquo;best practice&rdquo; coding techniques that you can use with your scripts. In yesterday&#8217;s post, I used the <b>&ndash;Strict<\/b> parameter with <b>Set-PSDebug<\/b>. This enforces the variable declaration in a script. But with <b>Set-StrictMode<\/b>, we get that plus a little more. The scope is limited to the current scope and child scopes. By default, <b>Set-StrictMode<\/b> is turned off to prevent error messages while you are writing the script.\nYou only have two parameters to deal with: <b>-Off<\/b> and <b>-Version<\/b>.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"67\" valign=\"top\">  <b>&nbsp;Off<\/b><\/p>\n<\/td>\n<td width=\"571\" valign=\"top\">\n<p>&nbsp;Turns off <b>StrictMode<\/b>.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"67\" valign=\"top\">\n<p><b>&nbsp;Version<\/b><\/p>\n<\/td>\n<td width=\"571\" valign=\"top\">\n<p>&nbsp;There are three possible values that can be supplied with this parameter:<\/p>\n<p><b>&nbsp;-Version 1.0<\/b><br \/>&nbsp;Prevents use of variables that have not been initialized (think <b>Option Explicit<\/b> in VBScript)<b><\/b><\/p>\n<p><b>&nbsp;-Version 2.0<\/b><\/p>\n<ul>\n<li>Prevents use of variables that have not been initialized (think <b>Option Explicit<\/b> in VBScript)<b><\/b><\/li>\n<li>Cannot call non-existent properties on objects<b><\/b><\/li>\n<li>Disallows calling a function like a method, for example, Do-Something(1 2)<b><\/b><\/li>\n<li>Prohibits creating variables without a name<\/li>\n<\/ul>\n<p><b>&nbsp;-Version Latest<\/b><br \/>&nbsp;Selects the latest <b>StrictMode<\/b> version available and uses that. This ensures that regardless of <br \/>&nbsp;which version &nbsp;of Windows PowerShell you are using, the latest version will be used.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Let&rsquo;s start by showing what happens when you set the <b>StrictMode<\/b> version to 1.0. We can verify that if we use an uninitialized variable, it will not throw any error messages and act as though it might actually have something.<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $i -gt 0<\/p>\n<p style=\"margin-left:30px\">False\nIt returned <b>$False<\/b>, which is what I expected. Now let&rsquo;s set the version to 1.0 and see what happens:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Set-StrictMode -Version 1.0<\/p>\n<p style=\"margin-left:30px\">$i -gt 0\nThe variable &#8216;$i&#8217; cannot be retrieved because it has not been set.<\/p>\n<p style=\"margin-left:30px\">At line:2 char:1<\/p>\n<p style=\"margin-left:30px\">+ $i -gt 0<\/p>\n<p style=\"margin-left:30px\">+ ~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo &nbsp; &nbsp; &nbsp; &nbsp; : InvalidOperation: (i:String) [], RuntimeException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;<span style=\"font-size:12px\">&nbsp; + FullyQualifiedErrorId : VariableIsUndefined<\/span>\nWell, that definitely played out differently. Instead of returning a Boolean value, I am greeted with an error message telling me that I should have initialized the variable first.\nAnother good use of this version is to make sure that you do not mistype a variable that might have been declared earlier and might not otherwise be caught.\nI would usually turn this off by using the <b>&ndash;Off<\/b> parameter, but instead, I am going to move to the next part of <b>Set-StrictMode<\/b> by running a few commands that will still succeed with version 1.0 enabled:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Function Invoke-Test {<\/p>\n<p style=\"margin-left:30px\">&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp; Param ($Item1, $Item2)<\/p>\n<p style=\"margin-left:30px\">&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp; $Item1 + $Item2<\/p>\n<p style=\"margin-left:30px\">&gt;&gt; }<\/p>\n<p style=\"margin-left:30px\">&gt;&gt;&nbsp;<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Invoke-Test(1,4)<\/p>\n<p style=\"margin-left:30px\">1<\/p>\n<p style=\"margin-left:30px\">4\nCalling the function like we would call a method worked&mdash;even with the version set to 1.0. This, of course, is not how a function should be called. It can cause undesirable problems if it happens to &ldquo;work&rdquo; because it treats the items separated by a comma as a collection. Setting the version to 2.0 (or to Latest) helps us understand that this is not an acceptable practice:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Set-StrictMode -Version 2.0<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Invoke-Test(1,4)\nThe function or command was called as if it were a method. Parameters should be separated by spaces. For information about parameters, see the about_Parameters Help topic.<\/p>\n<p style=\"margin-left:30px\">At line:1 char:1<\/p>\n<p style=\"margin-left:30px\">+ Invoke-Test(1,4)<\/p>\n<p style=\"margin-left:30px\">+ ~~~~~~~~~~~~~~~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidOperation: (:) [], RuntimeException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : StrictModeFunctionCallWithParens\nThat is more like it! After setting the version to 2.0 (or to Latest), my attempt to run the function like a method is met with an error message that explicitly says it was being called like a method. Remember that parameters are positional, and they should be separated by a space instead of a comma.\nNow I&rsquo;ll turn off <b>StrictMode<\/b> to demonstrate another example where something that shouldn&rsquo;t be used doesn&rsquo;t throw an error message. Then I&#8217;ll repeat the process with <b>StrictMode<\/b> enabled and set to Latest.<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Set-StrictMode &ndash;Off\nNow I will attempt to call a property on an object that doesn&rsquo;t exist:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $Item = &#8216;test&#8217;<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $item.date\nNothing happens. The property doesn&rsquo;t exist, but no error is thrown to let us know this.\nNow I enable <b>StrictMode<\/b> and observe what happens:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Set-StrictMode -Version Latest<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $item.date\nThe property &#8216;date&#8217; cannot be found on this object. Verify that the property exists.<\/p>\n<p style=\"margin-left:30px\">At line:1 char:1<\/p>\n<p style=\"margin-left:30px\">+ $item.date<\/p>\n<p style=\"margin-left:30px\">+ ~~~~~~~~~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : NotSpecified: (:) [], PropertyNotFoundException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : PropertyNotFoundStrict\nAs with my last demo, an attempt to use a property that doesn&rsquo;t exist on the object is rejected, and an associated error message shows that you are not calling a valid property name.\nJoin me tomorrow when I discuss using <b>Trace-Command<\/b> to help in troubleshooting the pipeline and parameter binding.\nWe invite you to follow the Scripting Guy on&nbsp;<a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a>&nbsp;and&nbsp;<a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to the Scripting Guy at&nbsp;<a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the&nbsp;<a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. Until then, see ya!\n<b>Boe Prox<\/b>, Windows PowerShell MVP and Honorary Scripting Guy<span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Boe Prox shows how to use Set-StrictMode to write better scripts. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the third part in a series of five posts about troubleshooting Windows PowerShell scripts and functions. The series includes: Provide Support [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[162,295,3,134,45],"class_list":["post-254","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-boe-prox","tag-debug","tag-scripting-guy","tag-troubleshooting","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Boe Prox shows how to use Set-StrictMode to write better scripts. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the third part in a series of five posts about troubleshooting Windows PowerShell scripts and functions. The series includes: Provide Support [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=254"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/254\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=254"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}