{"id":11961,"date":"2011-11-27T00:01:00","date_gmt":"2011-11-27T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/11\/27\/modify-a-powershell-script-to-accept-piped-input\/"},"modified":"2011-11-27T00:01:00","modified_gmt":"2011-11-27T00:01:00","slug":"modify-a-powershell-script-to-accept-piped-input","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/modify-a-powershell-script-to-accept-piped-input\/","title":{"rendered":"Modify a PowerShell Script to Accept Piped Input"},"content":{"rendered":"<p><b>Summary<\/b>: Learn how to modify a Windows PowerShell script and turn it into an advanced function that accepts piped input and has complete Help.<\/p>\n<h2><span class=\"Apple-style-span\" style=\"font-size: 12px;font-weight: normal\">Microsoft Scripting Guy, Ed Wilson, is here. Some things end up being way more complicated than they might appear at first glance. Today&rsquo;s script is a case in point. I decided I wanted to change <\/span><a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/11\/26\/use-powershell-to-find-out-who-has-permissions-to-a-share.aspx\" target=\"_blank\" style=\"font-size: 12px;font-weight: normal\">the script from yesterday<\/a><span class=\"Apple-style-span\" style=\"font-size: 12px;font-weight: normal\">, and put it into a function to make it more portable.<\/span><\/h2>\n<p>I also decided to add a few other features. I ended up spending the entire day working on the script. Of course, there was a meeting (I had to record the TechNet Radio pod cast. You can find it on the <a href=\"http:\/\/technet.microsoft.com\/en-us\/scriptcenter\/dd742419.aspx\" target=\"_blank\">Scripting with Windows PowerShell<\/a> site, just below PowerShell Quiz). <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/Get-Share-Users-rev2-6b84f5aa\" target=\"_blank\">The complete script<\/a> appears in the Script Center Script Repository.<\/p>\n<p>The first thing I did was use the <b>Function<\/b><i> <\/i>keyword&mdash;I specified a name and opened a pair of curly brackets (script block). I then added comment-based Help by using my <b>Add-Help<\/b> function from my way cool <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/21\/create-a-really-cool-powershell-ise-profile.aspx\" target=\"_blank\">Windows PowerShell ISE profile<\/a>. This portion of the script is shown here.<\/p>\n<p style=\"padding-left: 30px\"><b>Function Get-ShareUsers<\/b><\/p>\n<p style=\"padding-left: 30px\">{<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &lt;#<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Synopsis<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; This returns user name and sid of people with permission to a share<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Description<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; This function returns user name and sid of users with permission to<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; a share. It works locally or remotely, and accepts alternate credentials<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; for remote connections<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Example<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; &#8220;data&#8221; | Get-ShareUsers<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Returns information about who has access to the data share on the<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; local computer<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Example<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; &#8220;data&#8221;,&#8221;shared&#8221; | Get-ShareUsers -cn hyperv1 -credential administrator<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Prompts for credentials of administrator on a remote server named hyperv1<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; and returns users with permissions on the shared and the data shares<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Example<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; $shares = @()<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; gwmi win32_share -cn hyperv1 -cred (Get-Credential) -Filter &#8220;type=0&#8221; |<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; % { $shares += $_.name.tostring() }<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; $shares | Get-ShareUsers -cn hyperv1 -cred administrator<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; This example queries WMI to create an array of share names on a remote server<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; It then pipelines that array to the Get-ShareUsers function where it connects<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; to a remote server named hyperv1 using administrator credentials<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Parameter Credential<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; The user name to use for Get-Credential when connecting remotely<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Parameter Share<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; The name of the share to return information about<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; .Parameter cn<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; The name of the remote computer.<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Notes<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; NAME:&nbsp; Get-ShareUsers<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; AUTHOR: ed wilson, msft<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; LASTEDIT: 11\/22\/2011 18:04:10<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; KEYWORDS: Windows PowerShell, Scripting Guy!, Weekend Scripter, storage,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; shared folders and mapped drives, security<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; HSG: WES-11-27-11<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; .Link<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; Http:\/\/www.ScriptingGuys.com<\/p>\n<p style=\"padding-left: 30px\">&nbsp;#Requires -Version 2.0<\/p>\n<p style=\"padding-left: 30px\">&nbsp;#&gt;<\/p>\n<p>Next, I specify that I want to use <b>CmdletBinding<\/b>. I also make the <i>Share <\/i>parameter mandatory, and I set it up to accept piped input. The <b>CmdletBinding<\/b> and the parameter section of the script are shown here.<\/p>\n<p style=\"padding-left: 30px\">[CmdletBinding()]<\/p>\n<p style=\"padding-left: 30px\">&nbsp;Param (<\/p>\n<p style=\"padding-left: 30px\">&nbsp; [string]$credential,<\/p>\n<p style=\"padding-left: 30px\">&nbsp; [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)]<\/p>\n<p style=\"padding-left: 30px\">&nbsp; [string]$share,<\/p>\n<p style=\"padding-left: 30px\">&nbsp; [string]$cn = $env:COMPUTERNAME<\/p>\n<p style=\"padding-left: 30px\">&nbsp;)<\/p>\n<p>In the <i>Begin <\/i>portion of my function, I setup my splatting. I create an empty hash table named <i>RemoteParam<\/i>,<i> <\/i>and then I add the <i>Credential <\/i>and the <i>ComputerName <\/i>values to the hash table. This portion of the script is shown here.<\/p>\n<p style=\"padding-left: 30px\">BEGIN<\/p>\n<p style=\"padding-left: 30px\">&nbsp;{<\/p>\n<p style=\"padding-left: 30px\">&nbsp; $remoteParam = @{}<\/p>\n<p style=\"padding-left: 30px\">&nbsp; if($credential) { $remoteParam.add( &#8220;Credential&#8221;, (Get-Credential $credential))<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $remoteParam.Add( &#8220;Computername&#8221;, $cn) }<\/p>\n<p style=\"padding-left: 30px\">&nbsp;}<\/p>\n<p>I then create the <i>Process <\/i>portion of the function. I use the automatic variable <b>$input<\/b> to display the current item that is piped to the function. I then use the <b>$query<\/b> from yesterday&rsquo;s script. This portion of the <i>Process <\/i>block is shown here.<\/p>\n<p style=\"padding-left: 30px\">PROCESS {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; $input<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; $query = &#8220;Associators of {win32_LogicalShareSecuritySetting=&#8217;$share&#8217;}<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; Where resultclass = win32_sid&#8221;<\/p>\n<p>I modify the <b>Get-WmiObject<\/b> command to use splatting to accept the <i>ComputerName<\/i> and <i>Credential<\/i> parameters. I only pass these if the <i>Credential <\/i>parameter appears on the command line. Here is the modified <b>Get-WmiObject<\/b> command.<\/p>\n<p style=\"padding-left: 30px\">Get-WmiObject -query $query @RemoteParam<\/p>\n<p>The remainder of the function is the same as yesterday&rsquo;s script; and therefore, I will not go over it. It is shown here, for the sake of completeness.<\/p>\n<p style=\"padding-left: 30px\">Select-Object -Property @{LABEL=&#8221;User&#8221;;EXPRESSION=<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; {&#8220;{0}\\{1}&#8221; -f $_.ReferencedDomainName, $_.AccountName}}, SID<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; }<\/p>\n<p style=\"padding-left: 30px\">} #end function Get-ShareUsers<\/p>\n<p>To use the <b>Get-ShareUsers<\/b> function, I pipe a shared folder name to it. Here is an example command.<\/p>\n<p style=\"padding-left: 30px\">&#8220;Data&#8221; | Get-ShareUsers -credential administrator -cn hyperv1<\/p>\n<p>The command and its associated output are shown in the following image.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6237.hsg-11-27-11-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6237.hsg-11-27-11-01.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>I can pipe an array of share names to the function. This is shown here.<\/p>\n<p style=\"padding-left: 30px\">&#8220;shared&#8221;,&#8221;data&#8221; | Get-ShareUsers -credential administrator -cn hyperv1<\/p>\n<p>The command and its associated output are shown in the following image.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8272.hsg-11-27-11-02.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8272.hsg-11-27-11-02.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>One of the cool things to do with this function, is to use WMI to create an array of share names. Here is some code that does that.<\/p>\n<p style=\"padding-left: 30px\">$shares = @()<\/p>\n<p style=\"padding-left: 30px\">gwmi win32_share -cn hyperv1 -cred $cred -Filter &#8220;type=0&#8221; |<\/p>\n<p style=\"padding-left: 30px\">% { $shares += $_.name.tostring() }<\/p>\n<p>When I have the shares in an array, I can pipe the array to the <b>Get-ShareUsers<\/b> function. The syntax to do this is shown here.<\/p>\n<p style=\"padding-left: 30px\">$shares | Get-ShareUsers -credential administrator -cn hyperv1<\/p>\n<p>The commands and the associated output are shown in the following image.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/0830.hsg-11-27-11-03.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/0830.hsg-11-27-11-03.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Well, this is about all for messing around with shares and who has permissions to them. Remember, the complete script is in the <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/Get-Share-Users-rev2-6b84f5aa\" target=\"_blank\">Scripting Guys Script Repository<\/a>.<\/p>\n<p>If you are going to be in Pittsburg, Pennsylvania on December 13, 2011, you should check out the <a href=\"http:\/\/www.powershellgroup.org\/Pittsburgh.PA\" target=\"_blank\">Pittsburgh PowerShell Users Group meeting<\/a>. The Scripting Wife and I will be there, and I will be speaking about Windows PowerShell Best Practices. It will be awesome!<\/p>\n<p>Join me tomorrow as I begin a new week on the Hey, Scripting Guy! Blog. Oh, by the way, have you noticed that now we have more&nbsp;<a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/windows+powershell\/vbscript\/vbscript+migration\/\" target=\"_blank\">Windows PowerShell articles<\/a>&nbsp;on the Hey, Scripting Guy! Blog than&nbsp;<a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/vbscript\/\" target=\"_blank\">VBScript articles<\/a>? This is cool!<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to modify a Windows PowerShell script and turn it into an advanced function that accepts piped input and has complete Help. Microsoft Scripting Guy, Ed Wilson, is here. Some things end up being way more complicated than they might appear at first glance. Today&rsquo;s script is a case in point. I decided [&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":[3,63,185,12,61,45],"class_list":["post-11961","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-security","tag-shared-folders-and-mapped-drives","tag-storage","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to modify a Windows PowerShell script and turn it into an advanced function that accepts piped input and has complete Help. Microsoft Scripting Guy, Ed Wilson, is here. Some things end up being way more complicated than they might appear at first glance. Today&rsquo;s script is a case in point. I decided [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/11961","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=11961"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/11961\/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=11961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=11961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=11961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}