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.
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.
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.
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