Export Remote Shares and Folder permissions using PowerShell

We have recently been looking to audit some Windows servers shares and folder permissions. I have previously used a script to export folder permissions, so some of this script will be from that previous script. The main difference is that we will be using WMI query to get the list of shares and a looping through specified servers.

To get the list of shares we will use the Win32_Share WMI class and filtered out the default shares.

Get-WmiObject -ComputerName $Server -Class win32_share -Filter "Description != 'Remote Admin' and Description != 'Default share' and Description != 'Remote IPC' and Description != 'Printer Drivers'" | Select-Object Name -ExpandProperty Name

The full script that will be used is located on my Github repository, see link below.

Scripts/Get-SharesAndPermissions.ps1 at master · TheSleepyAdmin/Scripts (github.com)

To run the script use the below and update the exportpath and servers. To add multiple server just a comma between server names.

.\Get-SharesAndPermissions.ps1 -ExportPath D:\Scripts\Folder_Permissions\Export -Servers Server1, Server2

Once the script has completed the result will be export to a csv in the exported folder path.

24 thoughts on “Export Remote Shares and Folder permissions using PowerShell

  1. Thanks for the script. When I try to start it, I am getting below error message.

    .\aa.bat : .\Get-SharesAndPermissions.ps1 : The term ‘.\Get-SharesAndPermissions.ps1’ is not recognized as the name of a
    cmdlet, f
    At line:1 char:1
    + .\aa.bat
    + ~~~~~~~~
    + CategoryInfo : NotSpecified: (.\Get-SharesAnd… of a cmdlet, f:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

    unction, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the p
    ath is correct and try again.
    At line:1 char:1
    + .\Get-SharesAndPermissions.ps1 -ExportPath C:\Temp\Export -Servers E7 …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (.\Get-SharesAndPermissions.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Like

    1. Hi Joseph

      If you use .\Get-SharesAndPermissions.ps1, the PowerShell console needs to be in the same directory as the script or it wont be able to find the script and return the above error. If you have the script in a different directory you can just update the command to run the script from the specific location like c:\scirptlocation\Get-SharesAndPermissions.ps1

      Like

  2. Thanks for your reply. It worked now. Just one more information I need.

    I have shared folder like below but report doesnt biring \\Computername\Folder1 permissons to the list. If \\Computername\Folder1 has child folder like \\Computername\Folder1\Folder2 then it brings permisson of \\Computername\Folder1\Folder2.

    \\Computername\Folder1

    How can i get permission report of \\Computername\Folder1?

    Like

    1. The script is using get-childitem which doesn’t get information from the root directory only folders under the root. To get the root it would need to use get-item command and then added that to the folders variable. I would have to test but I think adding the two lines below should get the root folder.

      around line 42 of the script just between write-warning and $error.clear() clear, add

      $rootfolder = Get-Item -Path $FolderPath | Select-Object Name,FullName,LastWriteTime,Length

      then before the foreach loop on line 51 add the root directory to the folders variable using the below.

      $Folders += $rootfolder

      Like

  3. Thanks for your reply. Yes it worked now but now didint bring child folder now. Just gave root permission and if there is a folder in that share , gives below errror message.

    I need root permissons and folders permission in the share.

    Like

    1. hm ran it on my laptop since I don’t have any file share to connect to at the moment and it returned the root and the folders, it doesn’t get folders more than one level down though.

      I don’t see any error

      what I changed was

      Write-Warning “Checking permissions $($FolderPath)”

      ## Get Folders
      $error.clear()
      $Folders = Get-ChildItem -Path $FolderPath -Directory | Select-Object Name,FullName,LastWriteTime,Length -ErrorAction SilentlyContinue
      foreach ($err in $Error) {
      $err.Exception.Message | Out-File $ExportPath\AccessDenied.txt -Append
      }

      to

      Write-Warning “Checking permissions $($FolderPath)”

      ## Get Root Folder Permissions
      $rootfolder = Get-Item -Path $FolderPath | Select-Object Name,FullName,LastWriteTime,Length

      ## Get Folders
      $error.clear()
      $Folders = Get-ChildItem -Path $FolderPath -Directory | Select-Object Name,FullName,LastWriteTime,Length -ErrorAction SilentlyContinue
      foreach ($err in $Error) {
      $err.Exception.Message | Out-File $ExportPath\AccessDenied.txt -Append
      }

      $Folders += $rootfolder

      Like

  4. I changed same actually but it doesnt work.

    \\Computer1\Share1 is my share. If there is any child folder, it works but if there is folder in the share it get error and doesnt bring anything.\\Computer1\Share1\Share2

    Here error code.

    Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named ‘op_Addition’.
    At C:\Temp\Export\SharesAndPermissions.ps1:53 char:1
    + $Folders += $rootfolder
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

    Here my code.

    ## Setting script parameters
    param(
    [parameter(Mandatory = $true)]
    [String]$ExportPath,
    [parameter(Mandatory = $true)]
    [String[]]$Servers
    )

    ## Results variable
    $results = @()

    ## Lopping through specified servers
    Foreach ($Server in $Servers){

    Write-Host “Checking $($server)” -ForegroundColor Green

    ## query WMI for shares
    $Shares = Get-WmiObject -ComputerName $Server -Class win32_share -Filter “Description != ‘Remote Admin’ and Description != ‘Default share’ and Description != ‘Remote IPC’ and Description != ‘Printer Drivers'” | Select-Object Name -ExpandProperty Name

    ## Lopping through Shares
    foreach ($share in $Shares) {

    ## Creating folderpath variable
    $FolderPath = “\\$Server\$share”

    Write-Warning “Checking permissions $($FolderPath)”

    ## Get Root Folder Permissions
    $rootfolder = Get-Item -Path $FolderPath | Select-Object Name,FullName,LastWriteTime,Length

    ## Get Folders
    $error.clear()
    $Folders = Get-ChildItem -Path $FolderPath -Directory | Select-Object Name,FullName,LastWriteTime,Length -ErrorAction SilentlyContinue
    foreach ($err in $Error) {
    $err.Exception.Message | Out-File $ExportPath\AccessDenied.txt -Append
    }

    $Folders += $rootfolder

    ## Loop through folders
    foreach ($Folder in $Folders){

    ## Get access control list
    $Acls = Get-Acl -Path $Folder.FullName -ErrorAction SilentlyContinue

    ## Loop through ACL
    foreach ($Acl in $Acls.Access) {

    if ($Acl.IdentityReference -notlike “BUILTIN\Administrators” -and $Acl.IdentityReference -notlike “CREATOR OWNER” -and
    $Acl.IdentityReference -notlike “NT AUTHORITY\SYSTEM” -and $Acl.FileSystemRights -notlike “-*” -and $Acl.FileSystemRights -notlike “268435456”`
    -and $Acl.IdentityReference -notlike “S-1-*”){

    ## format properties for result hash table
    $properties = @{
    FolderName = $Folder.Name
    FolderPath = $Folder.FullName
    IdentityReference = $Acl.IdentityReference.ToString()
    Permissions = $Acl.FileSystemRights
    AccessControlType = $Acl.AccessControlType.ToString()
    IsInherited = $Acl.IsInherited
    }
    $results += New-Object psobject -Property $properties
    }
    }

    }
    }
    }
    ## Export results
    $results | Select-Object FolderName,FolderPath,IdentityReference,Permissions,AccessControlType,IsInherited |
    Export-Csv -Path $ExportPath\Share_PermissionExport.csv -NoTypeInformation

    Like

    1. ah ok it took me a bit to recreate the issue. It looks like it can’t add to the variable correctly. I changed it to the below and that worked for me.

      ## Get Root Folder Permissions
      $Folders = @(Get-Item -Path $FolderPath | Select-Object Name,FullName,LastWriteTime,Length)

      ## Get Folders
      $error.clear()
      $Folders += Get-ChildItem -Path $FolderPath -Directory | Select-Object Name,FullName,LastWriteTime,Length -ErrorAction SilentlyContinue
      foreach ($err in $Error) {
      $err.Exception.Message | Out-File $ExportPath\AccessDenied.txt -Append
      }

      Like

  5. May I ask last question. How can i go to 3 or 4 folder down? I mean ,

    Is it possible to get permissions for share3?

    \\Computer1\Share1\Share2\Share3

    Like

    1. If you want to get all sub folders just add the recurse parameter to the get-childitem and it should get all the sub folders. It might take a while depending on the number of folders.

      change

      $Folders += Get-ChildItem -Path $FolderPath -Directory | Select-Object Name,FullName,LastWriteTime,Length -ErrorAction SilentlyContinue

      to
      $Folders += Get-ChildItem -Path $FolderPath -Directory -Recurse | Select-Object Name,FullName,LastWriteTime,Length -ErrorAction SilentlyContinue

      Like

  6. Thank you so much for that script.
    I was looking for something that could replace shareenum and accessenum, due to those not working in certain network configurations.

    One note though, I noticed that if server name contains any “-” characters, -path argument can fail.
    Using -LiteralPath argument fixed it for me.

    Like

  7. Not the double quotes, I meant the minus ( – ) character inside of them.
    For example if you have your sharing servers seen in network as: srvr-tom1, srvr-tom2

    When script is using “Get-Item -Path $FolderPath”.
    “$FolderPath” contains “$Server” variable inside of itself.
    And for some reason “-Path” argument treats ” – ” as end of the line.
    Unless you meant double quotes that exist in the script at line 37, but changing those to single quotes didn’t change anything for me.
    Hence why I used “-literalPath”.

    Anyway, again, great script, great work.

    Like

  8. Is it difficult to modify this so only the actual share is listed (no folders underneath), along with any user or group and it’s SHARE permissions, sans any NTFS permissions?

    So output is: sharename, folder path, and then each user or group and what the Share side permissions are.

    Like

    1. Hi LT. Dan

      Its not that difficult but it would take a little bit of rewriting. I think if line 49 in the script was removed that would just get the top level folder and it permission. The share permission are not in Get-ACL, think it is in a WMI class so that would just need a bit of testing to get the correct info. I will try have a look at the weekend.

      Like

  9. the script need a lot of modification, or the authour need to read up on the diferences btween share and folder/file permisions. this script gives only folder/file permissions.

    Like

    1. I called out that the script only does folder permission and is only getting the list of shares from WMI and then exporting the folder permission for those shares.

      If the script doesn’t do what you want your a free to modify or write your own. If you read the description the script maybe you will save your self some time.

      .DESCRIPTION
      This Script is used to check for all shares on the specified servers and to export folder permission, the default shares like Admin$ and c$
      are excluded from this script.

      Like

  10. Awesome script. It does work for me. Thank you so much

    quick question, how would you exclude a particular shared folder.

    Exclude: \\server\share1$

    Thanks for your help.

    Like

    1. Hi Ron

      I am excluding shares using the WMI query on line 34.

      So the share will need a description added if there is not one there and then add an and Description != ‘Share description’ to after one of the exsting query or at the end before the double quotes.

      $Shares = Get-WmiObject -ComputerName $Server -Class win32_share -Filter “Description != ‘Remote Admin’ and Description != ‘Default share’ and Description != ‘Remote IPC’ and Description != ‘Printer Drivers’ and Description != ‘Share description'” | Select-Object Name -ExpandProperty Name

      Like

  11. Hi , when I run this locally , and point to the server name on the lan which is a clustered server I get Cannot find path ‘\\SERVERNAME\\\SERVERNAME\D$’ because it does not exist. Any ideas? Server 2016

    Like

    1. Hi cjrainey

      Without having the full error its hard to say but it does sound like either the account accessing the share doesn’t have permission or the path is not being correctly returned.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s