Archive for May, 2011


This month I find myself in the need for a quick way to do a simple audit on share permissions on a bunch of files servers. As always I wanted to use PowerShell Remoting (with the code executing on the local server) to accomplish this as enumerating shares is a slow process at the best of times and over the wire this would have been painfully slow.

Before writing a script I always see if anyone has done this already and in this case yes, I stumbled upon http://www.peetersonline.nl/index.php/powershell/listing-share-permissions-for-remote-shares

The only thing missing for my requirements was the need to have both the share name and server name adding to the object, this obviously is very minor and only required a couple of alterations, for example:

function Get-SharePermissions
{
	param([string]$computername,[string]$sharename)
	$ShareSec = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $computername
	ForEach ($ShareS in ($ShareSec | Where {$_.Name -eq $sharename}))
	{
		$SecurityDescriptor = $ShareS.GetSecurityDescriptor()
		$Global:myCol = @()
		ForEach ($DACL in $SecurityDescriptor.Descriptor.DACL)
		{
			$myObj = "" | Select ID, AccessMask, AceType
			$myObj.ID = $DACL.Trustee.Name
			$myObj | Add-Member -MemberType NoteProperty -Name Server -Value $computername
			$myObj | Add-Member -MemberType NoteProperty -Name Share -Value $sharename
			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}
			}
			$myObj.AccessMask = $AccessMask
			Switch ($DACL.AceType)
			{
				0 {$AceType = "Allow"}
				1 {$AceType = "Deny"}
				2 {$AceType = "Audit"}
			}
			$myObj.AceType = $AceType
			Clear-Variable AccessMask -ErrorAction SilentlyContinue
			Clear-Variable AceType -ErrorAction SilentlyContinue
			$myCol += $myObj
		}
	}
	Return $myCol
}

Get-SharePermissions -computername $ENV:COMPUTERNAME -sharename $args[0]

Like previous post on my blog I will use PowerShell remoting with a variable for the Servers ($allServers) and having saved the above code (C:\Scripts\Get-SharePermissions.ps1):

icm $allServers -FilePath C:\Scripts\Get-SharePermissions.ps1 -ArgumentList Wallpaper$

And the results:

Thanks for reading and I hope you find this useful. Also special thanks to the orginal author of this excellent script Hugo Peeters @ http://www.peetersonline.nl/

Regards,

jfrmilner


One of my clients was experiencing slow logon times after enabling roaming profiles and this was tracked down to large profiles. I needed to write a quick script that would tell me the folder size across a bunch of file servers.

I decided to create a function for this task named Get-FolderSize and this is the code:

function Get-FolderSize {
param ( [Parameter(Mandatory=$true)] [System.String]${Path}	)

$objFSO = New-Object -com  Scripting.FileSystemObject
$folders = (dir $path | ? {$_.PSIsContainer -eq $True})
foreach ($folder in $folders)
    {
    $folder | Add-Member -MemberType NoteProperty -Name "SizeMB" -Value (($objFSO.GetFolder($folder.FullName).Size) / 1MB) -PassThru
    }

}
Get-FolderSize $args[0]

To use this code on a local machine simply execute the above function and call it, for example Get-FolderSize D:\FileData. Now as previously mentioned I wanted to be able to check a large bunch of File Servers and to do that I would first need to create a variable to hold my servers, for example $allServers, then save the above code to the executing server for example C:\Scripts\Get-FolderSize.ps1. This finally allowed me to run the following command:

$folders = icm $allServers -FilePath C:\Scripts\Get-FolderSize.ps1 -ArgumentList "E:\Profiles"
 

Now to see the top 10 worst offenders with a filter to show only two decimal places:

 $folders | sort -Property SizeMB -Descending | select fullname,@{n='SizeMBN2';e={"{0:N2}" -f $_.SizeMB}} | select -First 10
 

Well as you can see from the below screen my client has some profiles to clean up but at least now they know which ones.

Thanks for reading and I hope you find this useful.

Regards,

jfrmilner


This month I find myself in the need for a quick way to do a simple audit of NTFS permissions on a bunch of files servers. As always I wanted to use PowerShell Remoting (with the code executing on the local server) to accomplish this as enumerating permissions is a slow process at the best of times and over the wire this would have been painfully slow.

Now I know that you can use some of the *CACLS executables to do this but if you’ve ever used these tools you will know they seem to default to information overload. All I wanted to do is get the permissions of a path and then check for any inheritance breaks on all its child folders, and be able to export to CSV.

This is the code that I came up with:

function Get-PathPermissions {

param ( [Parameter(Mandatory=$true)] [System.String]${Path}	)

	begin {
	$root = Get-Item $Path
	($root | get-acl).Access | Add-Member -MemberType NoteProperty -Name "Path" -Value $($root.fullname).ToString() -PassThru
	}
	process {
	$containers = Get-ChildItem -path $Path -recurse | ? {$_.psIscontainer -eq $true}
	if ($containers -eq $null) {break}
		foreach ($container in $containers)
		{
		(Get-ACL $container.fullname).Access | ? { $_.IsInherited -eq $false } | Add-Member -MemberType NoteProperty -Name "Path" -Value $($container.fullname).ToString() -PassThru
		}
	}
}
Get-PathPermissions $args[0]

To use this code on a local machine simply execute the above function and call it, for example Get-PathPermissions D:\FileData. Now as previously mentioned I wanted to be able to audit a large bunch of File Servers and to do that I would first need to create a variable to hold my servers, for example $allServers, then save the above code to the executing server for example C:\Scripts\Get-PathPermissions.ps1. This finally allowed me to run the following command:

icm $allServers -FilePath C:\Scripts\Get-PathPermissions.ps1 -ArgumentList "E:\WallPaper" | Export-Csv C:\PermissionsAudit.csv –NoTypeInformation

The output (C:\PermissionsAudit.csv) can now be manipulated in Excel, for example:

As you can see this provides very simple and easy to read output that can ease auditing NTFS permissions in bulk.

Thanks for reading and I hope you find this useful.

Regards,

jfrmilner