Public/Get-ACLInfo.ps1

function Get-ACLInfo {
  <#
      .SYNOPSIS
      Get a summary of a folder ACL
      .DESCRIPTION
      This command will examine the ACL of a given folder and create a custom object.
      The object will include a count of access rules based on the identity
      reference. Any ACL that belongs to a builtin or system account, or Everyone and
      Creator Owner, will be counted as a SystemACL. Everything else will be counted
      as a UserACL. You might use this information to identify folders or files where
      ACLS aren't what you expect.
 
      The custom object also contains an AccessRules property which will be a
      collection of the access rules for that object.
 
      SystemACL : 7
      Owner : BUILTIN\Administrators
      UserACL : 1
      AccessRules : {System.Security.AccessControl.FileSystemAccessRule, System.Security.
      AccessControl.FileSystemAccessRule, System.Security.AccessControl.
      FileSystemAccessRule, System.Security.AccessControl.FileSystemAccess
      Rule...}
      Path : C:\work
      TotalACL : 8
 
      It is assumed you will use this with the FileSystem provider.
 
      This version of the command uses a format file which is loaded "on the fly" so
      by default, information is presented as a nicely formatted table without the
      AccessRules property.
 
      .PARAMETER Path
      The path of the folder to analyze. The default is the current directory.
      .EXAMPLE
      PS C:\> Get-ACLInfo D:\Files
      Get acl data on the Files folder.
      .EXAMPLE
      PS C:\> dir e:\groups\data -recurse | where {$_.PSIsContainer} | get-aclinfo
      Get acl information for every folder under e:\groups\data.
      .NOTES
      NAME : Get-ACLInfo
      VERSION : 0.9
      LAST UPDATED: 6/21/2012
      AUTHOR : Jeffery Hicks (http://jdhitsolutions.com/blog)
      .LINK
      Get-ACL
      .INPUTS
      Strings
      .OUTPUTS
      Custom object
  #>

  [cmdletbinding()]
  Param(
    [Parameter(Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [ValidateScript({Test-Path -Path $_})]
    [string[]]$Path = '.'
  )
  Begin {
    Write-Verbose -Message ('Starting {0}' -f $myinvocation.mycommand)
    #create a format file on the fly
    $xml = @'
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
    <ViewDefinitions>
        <View>
            <Name>JDH.ACLInfo</Name>
            <ViewSelectedBy>
                <TypeName>JDH.ACLInfo</TypeName>
            </ViewSelectedBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Width>50</Width>
                    </TableColumnHeader>
                    <TableColumnHeader/>
                    <TableColumnHeader>
                      <Width>8</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                      <Width>9</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>7</Width>
                    </TableColumnHeader>
                </TableHeaders>
                <TableRowEntries>
                    <TableRowEntry>
                        <TableColumnItems>
                            <TableColumnItem>
                                <PropertyName>Path</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>Owner</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>TotalACL</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <Propertyname>SystemACL</Propertyname>
                            </TableColumnItem>
                             <TableColumnItem>
                                <Propertyname>UserACL</Propertyname>
                            </TableColumnItem>
                        </TableColumnItems>
                    </TableRowEntry>
                 </TableRowEntries>
            </TableControl>
        </View>
    </ViewDefinitions>
</Configuration>
'@

    #create a temp file
    $tmpfile = [IO.Path]::GetTempFileName()
    #add the necessary file extension
    $tmpfile += '.ps1xml'
    #pipe the xml text to the temp file
    Write-Verbose -Message ('Creating {0}' -f $tmpfile)
    $xml | Out-File -FilePath $tmpfile
    <#
        update format data. I'm setting error action to SilentlyContinue
        because everytime you run the function it creates a new temp file
        but Update-FormatData tries to reload all the format files it
        knows about in the current session, which includes previous versions
        of this file which have already been deleted.
    #>

    Write-Verbose -Message 'Updating format data'
    Update-FormatData -AppendPath $tmpfile -ErrorAction SilentlyContinue
  } #Begin
  Process {
    Foreach ($folder in $Path) {
      Write-Verbose -Message ('Getting ACL for {0}' -f $folder)
      #get the folder ACL
      $acl= Get-ACL -Path $folder
      #a regex to get a file path
      [regex]$regex = '\w:\\\S+'
      #get full path from ACL object
      $folderpath = $regex.Match($acl.Path).Value
      #get Access rules
      $access = $acl.Access
      #get builtin and system ACLS
      $sysACL= $access | Where-Object {$_.IdentityReference -match 'BUILTIN|NT AUTHORITY|EVERYONE|CREATOR OWNER'}
      #get non builtin and system ACLS
      $nonSysACL = $access | Where-Object {$_.IdentityReference -notmatch 'BUILTIN|NT AUTHORITY|EVERYONE|CREATOR OWNER'}
      #grab some properties and add them to a hash table.
      $hash = @{
        Path = $folderpath
        Owner = $acl.Owner
        TotalACL = $access.Count
        SystemACL = ($sysACL | measure-object).Count
        UserACL = ($nonSysACL | measure-object).Count
        AccessRules = $access
      }
      #write a new object to the pipeline
      $obj = New-object -TypeName PSObject -Property $hash
      #add a type name for the format file
      $obj.PSObject.TypeNames.Insert(0,'JDH.ACLInfo')
      $obj
    } #foreach
  } #Process
  End {
    #delete the temp file if it still exists
    if (Test-Path -Path $tmpfile) {
      Write-Verbose -Message ('Deleting {0}' -f $tmpfile)
      Remove-Item -Path $tmpFile
    }
    Write-Verbose -Message ('Ending {0}' -f $MyInvocation.MyCommand)
  } #end
}