Skip to content

Instantly share code, notes, and snippets.

@Trucido
Last active March 2, 2019 08:47
Show Gist options
  • Save Trucido/5d5aaa5920ae3968cffbc9a6a0e8d3bb to your computer and use it in GitHub Desktop.
Save Trucido/5d5aaa5920ae3968cffbc9a6a0e8d3bb to your computer and use it in GitHub Desktop.
## File: Get-FileAttributesEx.ps1
<#
.SYNOPSIS
Lists NTFS file or folder attributes and flags.
.DESCRIPTION
Lists many undocumented or otherwise inaccessible file attributes, flags, and ACL properties.
.PARAMETER Path
Path to file(s)/folder(s) to list properties. Wildcards and hidden or system files are supported.
.INPUTS System.Management.Automation.PathInfo, System.String
You can pipe PathInfo objects or strings that contain paths to this cmdlet.
.OUTPUTS System.Object, System.String
This cmdlet returns objects that it gets. The type is determined by the type of objects in the path.
.Example
PS> Get-FileAttributesEx ~\OneDrive\desktop.ini
FullName : C:\Users\User\OneDrive\desktop.ini
Owner : HOSTNAME\User
Group : HOSTNAME\None
Attributes : 1572870
AttributesEx : FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_SYSTEM, FILE_FLAG_UNKNOWN, FILE_FLAG_OPEN_NO_RECALL
AttributesHex : 0x00180006
IdentityReference : HOSTNAME\User
FileSystemRights : FullControl
AccessControlType : Allow
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
.NOTES
The FlagsAttribute list is incomplete and if several flags exist on a single item, results are
not always accurate. Many details of the FlagsAttribute class and other APIs are unknown
or undocumented as of this writing.
#>
#Requires -Version 5.1
function Get-FileAttributesEx {
[CmdletBinding()]
param(
[Parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string[]] $Path
)
# Begin{}
Set-Strictmode -Version 'Latest'
# https://docs.microsoft.com/en-us/windows/desktop/FileIO/file-attribute-constants
# https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea
[FlagsAttribute()]
enum FileAttributesEx
{
FILE_ATTRIBUTE_READONLY = 0x00000001
FILE_ATTRIBUTE_HIDDEN = 0x00000002
FILE_ATTRIBUTE_SYSTEM = 0x00000004
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
FILE_ATTRIBUTE_DEVICE = 0x00000040
FILE_ATTRIBUTE_NORMAL = 0x00000080
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
FILE_ATTRIBUTE_OFFLINE = 0x00001000
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000
FILE_ATTRIBUTE_VIRTUAL = 0x00010000
FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000
FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x00040000
FILE_FLAG_UNKNOWN = 0x00080000
FILE_FLAG_OPEN_NO_RECALL = 0x00100000
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x00400000
FILE_FLAG_SESSION_AWARE = 0x00800000
FILE_FLAG_POSIX_SEMANTICS = 0x01000000
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
FILE_FLAG_RANDOM_ACCESS = 0x10000000
FILE_FLAG_NO_BUFFERING = 0x20000000
FILE_FLAG_OVERLAPPED = 0x40000000
FILE_FLAG_WRITE_THROUGH = 0x80000000
}
# Use PWD if no args.
if (!$Path)
{
$Path = $PWD
}
# Assemble list of path arg(s). In the non-literal case we may need to resolve a wildcarded path.
foreach ($apath in $Path)
{
# Get-Item finds hidden and system files with -Force
if ($apath = Get-Item $apath -Force -ErrorAction:Ignore 2>$null)
{
$itemPaths += @($apath | Foreach-Object{$_.FullName})
}
else
{
$itemPaths += $apath
}
}
# Process{} ..the items we assembled.
foreach ($itempath in $itemPaths)
{
$item = Get-Item $itemPath -Force -ErrorAction:Ignore
# Add properties to $item
$itemAttributesEx = [FileAttributesEx]$item.Attributes.Value__
$itemHexAttributes = '0x{0:X8}' -f [int] $item.Attributes
Add-Member -InputObject $item -MemberType NoteProperty -Name AttributesEx -Value $itemAttributesEx
Add-Member -InputObject $item -MemberType NoteProperty -Name AttributesHex -Value $itemHexAttributes
$selectItemProperties = @("FullName", "Attributes", "AttributesEx", "AttributesHex")
# Try to add ACL properties. (Protected system files often throw error on `Get-ACL`)
# To list only attributes/flags; comment this entire Try/Catch block.
try
{
# ACL properties
$itemACL = Get-Acl $item -ErrorAction:Ignore 2>$null
Add-Member -InputObject $item -MemberType NoteProperty -Name ACL -Value $itemACL
Add-Member -InputObject $item -MemberType NoteProperty -Name Owner -Value $item.ACL.Owner
Add-Member -InputObject $item -MemberType NoteProperty -Name Group -Value $item.ACL.Group
# Add-Member -InputObject $item -MemberType NoteProperty -Name sddl -Value $item.ACL.SDDL
$selectItemProperties = @("FullName", "Owner", "Group", "Attributes", "AttributesEx", "AttributesHex")
# WindowsIdentity ACL access properties
$userIdentity = [Security.Principal.WindowsIdentity]::GetCurrent().Name
$itemACLuserIdentityaccess = $item.ACL.access | Where-Object{$_.IdentityReference -eq $userIdentity}
Add-Member -InputObject $item -MemberType NoteProperty -Name userAccess -Value $itemACLuserIdentityaccess
Add-Member -InputObject $item -MemberType NoteProperty -Name FileSystemRights -Value $item.userAccess.FileSystemRights
Add-Member -InputObject $item -MemberType NoteProperty -Name AccessControlType -Value $item.userAccess.AccessControlType
Add-Member -InputObject $item -MemberType NoteProperty -Name IdentityReference -Value $item.userAccess.IdentityReference
Add-Member -InputObject $item -MemberType NoteProperty -Name IsInherited -Value $item.userAccess.IsInherited
Add-Member -InputObject $item -MemberType NoteProperty -Name InheritanceFlags -Value $item.userAccess.InheritanceFlags
Add-Member -InputObject $item -MemberType NoteProperty -Name PropagationFlags -Value $item.userAccess.PropagationFlags
$selectItemProperties += @("IdentityReference", "FileSystemRights", "AccessControlType",
"IsInherited", "InheritanceFlags", "PropagationFlags" )
}
catch {}
# End{} return object(s) with a default set of selected properties attached; usually formatted in a table or list.
# Single properties may also be retrieved; Ex. (Get-FileAttributesEx "file").Owner
$item | Select-Object -Property $selectItemProperties
}
}
# If this script is invoked directly as opposed to being dot-sourced;
# invoke the embedded function relaying any arguments passed
if ($MyInvocation.ExpectingInput)
{
# True if we have ValueFromPipeLine $input (ExpectingInput)
$input | Get-FileAttributesEx @args
}
elseif (-not ($MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq ''))
{
# True if not dot-sourced or is invoked directly (empty invocation line)
Get-FileAttributesEx @args
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment