Modify a PowerShell Script to Accept Piped Input

Modify a PowerShell Script to Accept Piped Input

  • Comments 1
  • Likes

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’s script is a case in point. I decided I wanted to change the script from yesterday, and put it into a function to make it more portable.

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 Scripting with Windows PowerShell site, just below PowerShell Quiz). The complete script appears in the Script Center Script Repository.

The first thing I did was use the Function keyword—I specified a name and opened a pair of curly brackets (script block). I then added comment-based Help by using my Add-Help function from my way cool Windows PowerShell ISE profile. This portion of the script is shown here.

Function Get-ShareUsers

{

  <#

   .Synopsis

    This returns user name and sid of people with permission to a share

   .Description

    This function returns user name and sid of users with permission to

    a share. It works locally or remotely, and accepts alternate credentials

    for remote connections

   .Example

    "data" | Get-ShareUsers

    Returns information about who has access to the data share on the

    local computer

   .Example

    "data","shared" | Get-ShareUsers -cn hyperv1 -credential administrator

    Prompts for credentials of administrator on a remote server named hyperv1

    and returns users with permissions on the shared and the data shares

   .Example

    $shares = @()

    gwmi win32_share -cn hyperv1 -cred (Get-Credential) -Filter "type=0" |

    % { $shares += $_.name.tostring() }

    $shares | Get-ShareUsers -cn hyperv1 -cred administrator

    This example queries WMI to create an array of share names on a remote server

    It then pipelines that array to the Get-ShareUsers function where it connects

    to a remote server named hyperv1 using administrator credentials

   .Parameter Credential

    The user name to use for Get-Credential when connecting remotely

   .Parameter Share

    The name of the share to return information about

    .Parameter cn

     The name of the remote computer.

   .Notes

    NAME:  Get-ShareUsers

    AUTHOR: ed wilson, msft

    LASTEDIT: 11/22/2011 18:04:10

    KEYWORDS: Windows PowerShell, Scripting Guy!, Weekend Scripter, storage,

    shared folders and mapped drives, security

    HSG: WES-11-27-11

   .Link

     Http://www.ScriptingGuys.com

 #Requires -Version 2.0

 #>

Next, I specify that I want to use CmdletBinding. I also make the Share parameter mandatory, and I set it up to accept piped input. The CmdletBinding and the parameter section of the script are shown here.

[CmdletBinding()]

 Param (

  [string]$credential,

  [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)]

  [string]$share,

  [string]$cn = $env:COMPUTERNAME

 )

In the Begin portion of my function, I setup my splatting. I create an empty hash table named RemoteParam, and then I add the Credential and the ComputerName values to the hash table. This portion of the script is shown here.

BEGIN

 {

  $remoteParam = @{}

  if($credential) { $remoteParam.add( "Credential", (Get-Credential $credential))

                   $remoteParam.Add( "Computername", $cn) }

 }

I then create the Process portion of the function. I use the automatic variable $input to display the current item that is piped to the function. I then use the $query from yesterday’s script. This portion of the Process block is shown here.

PROCESS {

   $input

   $query = "Associators of {win32_LogicalShareSecuritySetting='$share'}

   Where resultclass = win32_sid"

I modify the Get-WmiObject command to use splatting to accept the ComputerName and Credential parameters. I only pass these if the Credential parameter appears on the command line. Here is the modified Get-WmiObject command.

Get-WmiObject -query $query @RemoteParam

The remainder of the function is the same as yesterday’s script; and therefore, I will not go over it. It is shown here, for the sake of completeness.

Select-Object -Property @{LABEL="User";EXPRESSION=

    {"{0}\{1}" -f $_.ReferencedDomainName, $_.AccountName}}, SID

   }

} #end function Get-ShareUsers

To use the Get-ShareUsers function, I pipe a shared folder name to it. Here is an example command.

"Data" | Get-ShareUsers -credential administrator -cn hyperv1

The command and its associated output are shown in the following image.

Image of command output

I can pipe an array of share names to the function. This is shown here.

"shared","data" | Get-ShareUsers -credential administrator -cn hyperv1

The command and its associated output are shown in the following image.

Image of command output

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.

$shares = @()

gwmi win32_share -cn hyperv1 -cred $cred -Filter "type=0" |

% { $shares += $_.name.tostring() }

When I have the shares in an array, I can pipe the array to the Get-ShareUsers function. The syntax to do this is shown here.

$shares | Get-ShareUsers -credential administrator -cn hyperv1

The commands and the associated output are shown in the following image.

Image of command output

Well, this is about all for messing around with shares and who has permissions to them. Remember, the complete script is in the Scripting Guys Script Repository.

If you are going to be in Pittsburg, Pennsylvania on December 13, 2011, you should check out the Pittsburgh PowerShell Users Group meeting. The Scripting Wife and I will be there, and I will be speaking about Windows PowerShell Best Practices. It will be awesome!

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 Windows PowerShell articles on the Hey, Scripting Guy! Blog than VBScript articles? This is cool!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    you presented a  wonderful powershell advanced function here!

    Using the pipeline to stream share names to it, is a brilliant idea!

    There is one thing, I would recommend to change her:

    The output of the share names is a bit confusing, as far as I'm concerned.

    I would prefer to see it as a column in the output table ( even if it is repeated for each permission)

    We can change the process block to do so:

    PROCESS {

      [string]$shareName=$input

      if (!$shareName) {$shareName = $share}

      $query = "Associators of {win32_LogicalShareSecuritySetting='$share'}  

      Where resultclass = win32_sid"

      Get-WmiObject -query $query @RemoteParam |  

      Select-Object -Property @{Label="Share"; Expression={$shareName}}, @{LABEL="User";EXPRESSION=

       {"{0}\{1}" -f $_.ReferencedDomainName, $_.AccountName}}, SID  

      }

    } #end function Get-ShareUsers

    The first two lines are inserted:

    I introduced a new variable $shareName that holds the currently piped object's name.

    If it isn't defined, it has not been piped and I can use the value of parameter $share instead.

    ( at least I hope so :-)

    The Select-object statement has been expanded to include the new "$shareName"  in the first column of the output which looks like that:

    PS C:\Users\Schulte> "C","Documents","SSM" | Get-ShareUsers

    Share                                     User                                     SID                                    

    -----                                     ----                                     ---                                    

    C                                         DOMS\Schulte                             S-1-5-21-705412637-4193279631-2871877...

    Documents                                 \Jeder                                   S-1-1-0                                

    Documents                                 VORDEFINIERT\Administratoren             S-1-5-32-544                            

    SSM                                       VORDEFINIERT\Administratoren             S-1-5-32-544                            

    SSM                                       \Jeder                                   S-1-1-0                                

    Klaus.