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.


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
LikeLike
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
LikeLike
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?
LikeLike
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
LikeLike
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.
LikeLike
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
LikeLike
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
LikeLike
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
}
LikeLike
Perfect. It worked. Thanks for your big support.
LikeLike
No problem, Glad it’s working for you.
LikeLike
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
LikeLike
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
LikeLike
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.
LikeLike
Hi Tom
Glad the script was of help. If there are double quotes its probable taking that as a literal break.
LikeLike
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.
LikeLike
Thanks Tom will take a look and see if I can recreate the issue and will update the script to use -literalpath
LikeLike
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.
LikeLike
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.
LikeLike
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.
LikeLike
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.
LikeLike
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.
LikeLike
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
LikeLike
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
LikeLike
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.
LikeLike
Hello, Thanks for the great script. Is there a way around these errors? I haven’t been added to this share, but I am a Local Admin, and I’m running PowerShell as an admin:
WARNING: Checking permissions \\SERVER1\Share1
Get-Item : Access is denied
At X:\Get-SharesAndPermissionsV2.ps1:45 char:14
+ $Folders = @(Get-Item -Path $FolderPath | Select-Object Name,FullName …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (\\SERVER1\Share1:String) [Get-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetItemCommand
Get-Item : Cannot find path ‘\\SERVER1\Share1’ because it does not exist.
At X:\Get-SharesAndPermissionsV2.ps1:45 char:14
+ $Folders = @(Get-Item -Path $FolderPath | Select-Object Name,FullName …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\SERVER1\Share1:String) [Get-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
Get-ChildItem : Access is denied
At X:\Get-SharesAndPermissionsV2.ps1:49 char:13
+ $Folders += Get-ChildItem -Path $FolderPath -Directory | Select-Obje …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (\\SERVER1\Share1:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
Get-ChildItem : Cannot find path ‘\\SERVER1\Share1’ because it does not exist.
At X:\Get-SharesAndPermissionsV2.ps1:49 char:13
+ $Folders += Get-ChildItem -Path $FolderPath -Directory | Select-Obje …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\SERVER1\Share1:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
LikeLike
Hi AI_H
From the error it’s cause the account that is running the script doesn’t have access to the folder. If you run Get-Item and the path on it’s own do you still get access denied. If so you might need to check the security properties of the folder and make sure the account has access.
LikeLike
Hi, thanx for the script. How do I run it against a list of servers in a txt or csv file?
LikeLike
Hi Tim
If you want to run against a list of server you would need to remove the server parameter and then create a new variable and use either get-content for txt file or import-csv. For csv you might need to also call the heading. Below would probable work for a txt file.
## Setting script parameters
param(
[parameter(Mandatory = $true)]
[String]$ExportPath
)
## Results variable
$results = @()
$Servers = Get-Content -Path c:\server.txt
## Lopping through specified servers
Foreach ($Server in $Servers){
LikeLike
hi thank you for the script but i want to exclude all the ADMIN$ folder but i don’t know how to do it can you help me pls
LikeLike
Hi Allan
The ADMINS$ share should be excluded as its the remote admin folder and the script is set to ignore that using the -Filter “Description != ‘Remote Admin’ on line 34.
LikeLike
i know but it is not excluded in my csv file there is the ADMIN$ and i don’t know why
LikeLike
I checked the script against one of my servers and it doesn’t return the admin$ share. The script is using the description to filter so possible that is different on yours. You could try run Get-WmiObject -ComputerName servername -Class win32_share and see what the description is for each share maybe it different.
LikeLike