Ever wanted to know what shares are on all your Servers

I have been scripting using VBScript for some time now, and only on occasion have I had the motivation and\or reason to write a script using Powershell, but I have decided in the last 9 months to make a concerted effort to utilise the Power of Powershell as my main scripting technology. In this time period I have produced a number of scripts and I will be adding them to my blog in case anybody finds them useful.

So my first offering is something I wrote for a colleague of mine, that queries all the Windows Servers in your domain and gathers their Shares, the permissions set on the shares and the permissions set on the NTFS file system at the share level (not lower). All this is output to 2 CSV files in the same folder that the script is run from. There are no Parameters for the script, and I hadn't written it to specifically search in specific OU structures or to read from text file based list of computers. I have since written another script that I will be posting here, that has this functionality, so if you need it that functionality it can be done.

The script requires that you have the necessary Rights on all the Servers you will be querying to get back all the information.

Below is a listing of the script, but I have attached the code in a text file as well (obviously remove the txt extension to use)..

<#
#####################################################################
SCRIPT GetPermissions.ps1
SYNOPSIS
    Gets all Servers from the domain from which the script is run in
    (i.e. the domain you are logged in to).
    Then uses the server list to query each servers Share permissions
    and the NTFS permissions of each share root folder.
    The Script creates 2 files in the same location the script is
    run from (sharereport.csv and ntfsreport.csv).
NOTE
    Script requires no parameters or arguments
    I recommend you have the relevant permissions in the domain and
    on the servers being queried for optimal results.
    Myself or my employer do not warrantee this script in any way and
    use of it is entirely at the users own risk.
    The working functions of this script are taken from examples found
    at Microsoft Script Center web site and are written by Boe Prox.
AUTHOR
    Carl Harrison
    The script utilises 2 functions written by Boe Prox and publically
    available at Microsoft Script Center. They have been altered slightly
    to work with this script.
VERSION: 1.0 - First cut
         1.1 - Sorted FQDN Ping instead of netbios ping
#####################################################################
#>

function Get-SharePermissions{
<# 
.SYNOPSIS 
    Retrieves share permissions. This function was extracted from a
    Powershell Module written by Boe Prox named FileSharePermissions.psm1
.DESCRIPTION
    Retrieves share permissions.
.PARAMETER computer
    Name of server to test.         
.EXAMPLE 
    Get-SharePermissions -computer Test         
#>
[cmdletbinding(
 DefaultParameterSetName = 'computer',
 ConfirmImpact = 'low'
)]
    Param(
        [Parameter(
            Mandatory = $True,
            Position = 0,
            ParameterSetName = 'computer',
            ValueFromPipeline = $True)]
            [array]$computer                     
            )
Begin
    {               
    #Process Share report
    $sharereport = @()
    }
Process
    {
    #Iterate through comptuers
    ForEach ($c in $computer)
        {
        Try
            {   
            #Write-Verbose "Computer: $($c)"
            #Retrieve share information from comptuer
            $ShareSec = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $c -ea stop
            ForEach ($Shares in $sharesec)
                {
                #Write-Verbose "Share: $($Shares.name)"
                    #Try to get the security descriptor
              $SecurityDescriptor = $ShareS.GetSecurityDescriptor()
                    #Iterate through each descriptor
              ForEach ($DACL in $SecurityDescriptor.Descriptor.DACL)
                        {
                        $arrshare = New-Object PSObject
                        $arrshare | Add-Member NoteProperty Computer $c
               $arrshare | Add-Member NoteProperty Name $Shares.Name
               $arrshare | Add-Member NoteProperty ID $DACL.Trustee.Name
                        #Convert the current output into something more readable
               Switch ($DACL.AccessMask)
                            {
                2032127 {$AccessMask = "FullControl"}
                1179785 {$AccessMask = "Read"}
                1180063 {$AccessMask = "Read, Write"}
                1179817 {$AccessMask = "ReadAndExecute"}
                -1610612736 {$AccessMask = "ReadAndExecuteExtended"}
                1245631 {$AccessMask = "ReadAndExecute, Modify, Write"}
                1180095 {$AccessMask = "ReadAndExecute, Write"}
                268435456 {$AccessMask = "FullControl (Sub Only)"}
                default {$AccessMask = $DACL.AccessMask}
                   }
               $arrshare | Add-Member NoteProperty AccessMask $AccessMask
                        #Convert the current output into something more readable
               Switch ($DACL.AceType)
                            {
                0 {$AceType = "Allow"}
                1 {$AceType = "Deny"}
                2 {$AceType = "Audit"}
                   }
               $arrshare | Add-Member NoteProperty AceType $AceType
                        #Add to existing array
                        $sharereport += $arrshare
                        }
              }
                }
            #Catch any errors               
            Catch
                {
                $arrshare = New-Object PSObject
                $arrshare | Add-Member NoteProperty Computer $c
       $arrshare | Add-Member NoteProperty Name "NA"
       $arrshare | Add-Member NoteProperty ID "NA"
                $arrshare | Add-Member NoteProperty AccessMask "NA"         
                #Add to existing array
                $sharereport += $arrshare
                }
            Finally
                {
                #Do Nothing Currently
                }                                                  
            }
        }                      
End {
    #Display report
    #$ShareReport
    #$ShareReport | Export-Csv -notypeinformation "sharereport.csv"
    return $sharereport
    }
}   

function Get-ShareNTFSPermissions{
<# 
.SYNOPSIS 
    Retrieves NTFS permissions on a share. This function was extracted from a
    Powershell Module written by Boe Prox named FileSharePermissions.psm1
.DESCRIPTION
   Retrieves NTFS permissions on a share.
.PARAMETER computer
    Name of server to test.         
.EXAMPLE 
    Get-ShareNTFSPermissions -computer Test       
#>
[cmdletbinding(
 DefaultParameterSetName = 'computer',
 ConfirmImpact = 'low'
)]
    Param(
        [Parameter(
            Mandatory = $True,
            Position = 0,
            ParameterSetName = 'computer',
            ValueFromPipeline = $True)]
            [array]$computer                     
            ) 
Begin
    {             
    #Process NTFS Share report               
    $ntfsreport = @()     
    }
    Process
    {
    #Iterate through each computer
    ForEach ($c in $computer)
        {
        Try
            {                
            Write-Verbose "Computer: $($c)"
            #Gather share information
            $shares = Gwmi -comp $c Win32_Share -ea stop | ? {$_.Name -ne 'ADMIN$'-AND $_.Name -ne 'C$' -AND $_.Name -ne 'IPC$'} | Select Name,Path
            ForEach ($share in $shares)
                {
                #Iterate through shares
                Write-Verbose "Share: $($share.name)"
                If ($share.path -ne "")
                    {
                    #Retrieve ACL information from Share 
                    $remoteshare = $share.path -replace ":","$"
                    Try
                        {
                        #Gather NTFS security information from each share
                        $acls = Get-ACL "\\$computer\$remoteshare"
                        #iterate through each ACL
                        ForEach ($acl in $acls.access)
                            {
                            If ($acl.FileSystemRights -match "\d")
                                {
                       Switch ($acl.FileSystemRights)
                                    {
                        2032127 {$AccessMask = "FullControl"}
                        1179785 {$AccessMask = "Read"}
                        1180063 {$AccessMask = "Read, Write"}
                        1179817 {$AccessMask = "ReadAndExecute"}
                        -1610612736 {$AccessMask = "ReadAndExecuteExtended"}
                        1245631 {$AccessMask = "ReadAndExecute, Modify, Write"}
                        1180095 {$AccessMask = "ReadAndExecute, Write"}
                        268435456 {$AccessMask = "FullControl (Sub Only)"}
                        default {$AccessMask = "Unknown"}
                           }                               
                                }
                            Else
                                {
                                $AccessMask = $acl.FileSystemRights
                                }                               
                            $arrntfs = New-Object PSObject                   
                            #Process NTFS Report        
                            $arrntfs | Add-Member NoteProperty Computer $c             
                            $arrntfs | Add-Member NoteProperty ShareName $Share.name
                            $arrntfs | Add-Member NoteProperty Path $share.path
                            $arrntfs | Add-Member NoteProperty NTFS_User $acl.IdentityReference
                            $arrntfs | Add-Member NoteProperty NTFS_Rights $AccessMask
                            $ntfsreport += $arrntfs
                            }   
                        }
                    Catch
                        {
                        $arrntfs = New-Object PSObject                   
                        #Process NTFS Report        
                        $arrntfs | Add-Member NoteProperty Computer $c             
                        $arrntfs | Add-Member NoteProperty ShareName "NA"
                        $arrntfs | Add-Member NoteProperty Path "NA"
                        $arrntfs | Add-Member NoteProperty NTFS_User "NA"
                        $arrntfs | Add-Member NoteProperty NTFS_Rights "NA"                   
                        #Add to existing array
                        $ntfsreport += $arrntfs
                        }
                    Finally
                        {
                        #Do nothing currently
                        }                                                                                  
                    }                              
                }
            }
        Catch
            {
            $arrntfs = New-Object PSObject
            $arrntfs | Add-Member NoteProperty Computer $c             
            $arrntfs | Add-Member NoteProperty ShareName "NA"
            $arrntfs | Add-Member NoteProperty Path "NA"
            $arrntfs | Add-Member NoteProperty NTFS_User "NA"
            $arrntfs | Add-Member NoteProperty NTFS_Rights "NA"        
            #Add to existing array
            $ntfsreport += $arrntfs        
            }
        Finally
            {
            #Do Nothing Currently
            }                                       
        }           
    }
    End
    {
    #Display report
    #$ntfsreport
    #$ntfsreport | Export-Csv -notypeinformation "ntfsreport.csv"
    return $ntfsreport
    }            
}

#THIS IS THE START OF THE SCRIPT

#Define Some variables and Arrays
$strOperatingSystem = "*Server*"
$Servers = @()
$ServersShareReport = @()
$ServersNTFSReport = @()

#Set up the Directory Search parameters
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("OperatingSystem=$strOperatingSystem")
$objSearcher.PageSize = 1000
 
#Define the Attributes we need from the search
$colProplist = "name","dnshostname","operatingsystemversion"
#Do the Search
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
$Ping = New-Object System.Net.NetworkInformation.Ping
ForEach ($objResult in $colResults)
    {
    $Server = $objResult.Properties.name
    $ServerDNS = $objResult.Properties.dnshostname
    Write-Host "Pinging $ServerDNS"
    $errorActionPreference="SilentlyContinue"
    $Pingy = $ping.send($ServerDNS,5000)
    $ServerShareOutput = $Null
    $ServerNTFSOutput = $Null
    Try
        {
        #This is where we go get the information
        If ($Pingy.status.tostring() –eq “Success”)
            {
            #Cool we can get to the server now lets gather some information
            write-host “$Server Available”
            $errorActionPreference="Continue"
            $ServerShareOutput = Get-SharePermissions -computer $ServerDNS
            $ServerNTFSOutput = Get-ShareNTFSPermissions -computer $ServerDNS
            $ServersShareReport += $ServerShareOutput
            $ServersNTFSReport += $ServerNTFSOutput
            }
        else
            {
            #oh-oh either WMI is restricted or we cannot get to the current server
            write-host “$Server Not Available"
            $FailedShareServer = New-Object PSObject
            $FailedShareServer | Add-Member NoteProperty Computer "$Server"
            $FailedShareServer | Add-Member NoteProperty Name "Server No Available"
            $ServersShareReport += $FailedShareServer
            $FailedNTFSServer = New-Object PSObject
            $FailedNTFSServer | Add-Member NoteProperty Computer "$Server"
            $FailedNTFSServer | Add-Member NoteProperty ShareName "Server No Available"
            $ServersNTFSReport += $FailedNTFSServer
            }
        }
    Catch
        {
        #And this just catches any weird error events
        write-host “$Server Not Available"
        $FailedShareServer = New-Object PSObject
        $FailedShareServer | Add-Member NoteProperty Computer "$Server"
        $FailedShareServer | Add-Member NoteProperty Name "Server Not Available"
        $ServersShareReport += $FailedShareServer
        $FailedNTFSServer = New-Object PSObject
        $FailedNTFSServer | Add-Member NoteProperty Computer "$Server"
        $FailedNTFSServer | Add-Member NoteProperty ShareName "Server Not Available"
        $ServersNTFSReport += $FailedNTFSServer
        }
    Finally
        {
        $errorActionPreference="Continue"
        $pingy = $null
        $Server = $Null
        }
    }
       
#Now we have the data let's save it to file - in the same location the script is run from
$ServersShareReport | Export-Csv -notypeinformation ".\sharereport.csv"
$ServersShareReport = @()
$ServersNTFSReport | Export-Csv -notypeinformation ".\ntfsreport.csv"
$ServersNTFSReport = @()

GetPermissions.ps1.txt