{"id":51033,"date":"2010-03-10T00:01:00","date_gmt":"2010-03-10T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/03\/10\/hey-scripting-guy-how-can-i-use-the-test-path-cmdlet-to-check-for-resources\/"},"modified":"2010-03-10T00:01:00","modified_gmt":"2010-03-10T00:01:00","slug":"hey-scripting-guy-how-can-i-use-the-test-path-cmdlet-to-check-for-resources","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-use-the-test-path-cmdlet-to-check-for-resources\/","title":{"rendered":"Hey, Scripting Guy! How Can I Use the Test-Path Cmdlet to Check for Resources?"},"content":{"rendered":"<p class=\"MsoNormal\"><a class=\"addthis_button\" href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\"><\/a><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"><\/p>\n<p class=\"MsoNormal\">Hey, Scripting Guy! Ignoring errors or bubbling up errors to the user of a script seems a bit inefficient. I mean, wouldn&rsquo;t it be better to avoid the errors in the first place? I am only a beginner when it comes to writing scripts, and maybe I just do not get it, but why can&rsquo;t you just write code that does not generate errors?<\/p>\n<p class=\"MsoNormal\">&#8212; KE<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello KE, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. One of the bad things about having a day filled with meetings is that it really disturbs one&rsquo;s schedule, disrupts one&rsquo;s rhythm, and derails the ebb and flow. Not that meetings are necessarily a bad thing, but there is a cost that must be factored into the equation&mdash;a cost not just measured in labor for meeting attendance. After all, there is meeting prep work, meeting follow-up work, and then the mental context switching that occurs when shifting from one task to a meeting and then back to the task. After spending most of yesterday in meetings, my workspace feels foreign, my Zune HD seems neglected, and my teapot is missing. To ease back into normal work mode, I thought I would catch up on some of the e-mail sent to <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a>. <\/p>\n<p class=\"MsoNormal\">KE, you are correct. Preventing errors is much more efficient than trapping errors. At times, this is relatively easy to do; on other occasions, it can be problematic to implement. There are a number of occasions when a few simple checks will improve the reliability of your script. <\/p>\n<p class=\"MsoNormal\">One of my favorite cmdlets is <b>Test-Path<\/b>. I use it before file and registry operations. In the Windows PowerShell shell, you can use the <b>Test-Path<\/b> cmdlet to see if a file exists. The cmdlet returns a Boolean value, and true means the file exists. It will return false if the file does not exist. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; test-path -Path c:fsotest.txt<br \/>True<br \/>PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If I am developing a script that will write to the test.txt file in the C:fso folder, I have a number of choices that I must make before getting too far in the process. The simplest solution is to delete the file if it exists, and create a new one. However, that may not be an acceptable solution. You may want to append to the file, or you may want to create a new file with a similar name. The &ldquo;correct&rdquo; solution is up to you, but it all hinges on detecting the existence of the file. This is where the <b>Test-Path<\/b> comes into play. <\/p>\n<p class=\"MsoNormal\">Because the first task is to see if the file exists or not, use an <b>if<\/b><i> <\/i>statement. In reality, we only need to know if the file does not exist. If it does not exist, we can create it. Because the <b>Test-Path<\/b> cmdlet returns true or false if the file exists, and we want to know if the file does not exist, we use the <b>not<\/b><i> <\/i>operator to reverse the logic. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">if(!(Test-Path -Path $path))<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If the file does not exist, create it by using the <b>New-Item<\/b> cmdlet. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">new-item -Path $path -Value &#8220;new file&#8221; &ndash;itemtype file<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If the file does exist, it will trigger the <b>Else<\/b><i> <\/i>clause. This is where we have to decide what we want to do if the file exists. In this example, we append to the text file by using the <b>Add-Content<\/b> cmdlet. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Add-Content -Path $path -Value &#8220;`r`n Additional content&#8221;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>CheckForFileAndAddContent.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$path = &#8220;c:fsotest.txt&#8221;<br \/>if(!(Test-Path -Path $path))<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>new-item -Path $path -Value &#8220;new file&#8221; &ndash;itemtype file<br \/><span>&nbsp; <\/span>}<br \/>else<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>Add-Content -Path $path -Value &#8220;`r`n Additional content&#8221;<br \/><span>&nbsp; <\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Each time the script runs, the words &ldquo;Additional content&rdquo; are added to the bottom of the Test.txt file. This is shown in the following image.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title='Image of words \"Additional content\" added to end of Test.txt' alt='Image of words \"Additional content\" added to end of Test.txt' src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/march\/hey0310\/hsg-03-10-10-01.jpg\" width=\"516\" height=\"476\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">Use the same technique when working with the registry. As seen in the CheckForRegistryKeyAndUpdate.ps1, you do not have to use the exclamation point (<b>!<\/b>) for the not operator. You can simply use <b>&ndash;not<\/b> if you wish. It makes the script more readable, but in general, I do not use it because of th\ne <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/2010\/02\/21\/hey-scripting-guy-february-21-2010.aspx\"><font face=\"Segoe\">extra typing that is involved<\/font><\/a>. When working with the registry, it is important to remember that the <b>Test-Path<\/b> cmdlet will not report correctly on a registry entry (registry key property); it always reports false. It does, however, correctly report on the registry keys themselves. The snippet is shown here (compare these paths with those seen in the next image in this post):<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; Test-Path -Path HKCU:SoftwareScriptingGuysTestupdate<br \/>False<br \/>PS C:&gt; Test-Path -Path HKCU:SoftwareScriptingGuysTest<br \/>True<br \/>PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Use the <b>Test-Path<\/b> cmdlet to check the path to the registry key, and if it does not exist, create both the registry key and the registry key property. This is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">If(-not(Test-Path -Path $path))<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>New-Item -Path $path -Force<br \/><span>&nbsp;&nbsp; <\/span>New-ItemProperty -Path $path -Name Update -Value &#8220;Updated&#8221;<br \/><span>&nbsp; <\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If the registry key does exist, we cannot determine if the registry key property exists; therefore, we use the <b>Set-ItemProperty<\/b> cmdlet. This will create the registry key property or update the key if it exists, which for our purpose is sufficient. This command is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Set-ItemProperty -Path $path -Name Update -Value &#8220;New Update&#8221;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The completed CheckForRegistryKeyAndUpdate.ps1 script is seen here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>CheckForRegistryKeyAndUpdate.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$path = &#8220;HKCU:SoftwareScriptingGuysTest&#8221;<br \/>If(-not(Test-Path -Path $path))<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>New-Item -Path $path -Force<br \/><span>&nbsp;&nbsp; <\/span>New-ItemProperty -Path $path -Name Update -Value &#8220;Updated&#8221;<br \/><span>&nbsp; <\/span>}<br \/>Else<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>Set-ItemProperty -Path $path -Name Update -Value &#8220;New Update&#8221;<br \/><span>&nbsp; <\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When the script runs, the registry entries shown in the following image appear.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of registry entries shown when script runs\" alt=\"Image of registry entries shown when script runs\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/march\/hey0310\/hsg-03-10-10-02.jpg\" width=\"600\" height=\"364\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">The cool thing about the <b>Test-Path<\/b> cmdlet is that it works with other Windows PowerShell providers. For example, before creating a new alias, you may wish to use the <b>Test-Path<\/b> cmdlet to see if the alias exists. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; Test-Path -Path alias:gc<br \/>True<br \/>PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">You could use this in a script as seen in CheckForAliasAndCreate.ps1. You can see that the process works in a similar manner as the other scripts we have created today. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>CheckForAliasAndCreate.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$path = &#8220;Alias:gc&#8221;<br \/>if(!(Test-Path -Path $path))<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>New-Alias -Name gc -Value Get-Credential <br \/><span>&nbsp; <\/span>}<br \/>else<br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>&#8220;Alias $path already exists&#8221;<br \/><span>&nbsp; <\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If you wish to check on the existence of a function, use the function drive with the <b>Test-Path<\/b> cmdlet as shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; Test-Path -Path Function:TabExpansion<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">True<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">You can use the <b>Test-Path<\/b> cmdlet to check for variables, by inspecting the variable drive. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; Test-Path -Path Variable:PSBoundParameters<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">True<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">This also works for the environmental drive, as shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; Test-Path -Path Env:ALLUSERSPROFILE<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">True<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If you need to know if a user has a particular certificate in the certificate store, use the certificate drive as shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; Test-Path -Path cert:CurrentUserAuthRootC31EB1E720E33C8102BADC37D44DE5D4674752A8<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">True<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">As you can see, using the <b>Test-Path<\/b> cmdlet with the certificate drive can pose some challenges, because you have to use the thumbprint of the certificate. <\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<p class=\"MsoNormal\">KE, that is all there is to using the Test-Path cmdlet to check for resources before taking action. Error Handling Week will continue tomorrow when we will talk about&hellip;wait a minute. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\"><font face=\"Segoe\">Twitter<\/font><\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send e-mail to us at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\"><font face=\"Segoe\">Official Scripting Guys Forum<\/font><\/a>. See you tomorrow. Until then, peace.<\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/p>\n<p><\/span><\/b><\/p>\n<p><b><span><\/span><\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! Ignoring errors or bubbling up errors to the user of a script seems a bit inefficient. I mean, wouldn&rsquo;t it be better to avoid the errors in the first place? I am only a beginner when it comes to writing scripts, and maybe I just do not get it, but why [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[68,51,3,4,45],"class_list":["post-51033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-error-handling","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! Ignoring errors or bubbling up errors to the user of a script seems a bit inefficient. I mean, wouldn&rsquo;t it be better to avoid the errors in the first place? I am only a beginner when it comes to writing scripts, and maybe I just do not get it, but why [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51033","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\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=51033"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51033\/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=51033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=51033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=51033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}