Skip to content

Instantly share code, notes, and snippets.

@Trucido
Created March 11, 2019 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Trucido/02dc6b7f43df1eb6f0e5146f77282143 to your computer and use it in GitHub Desktop.
Save Trucido/02dc6b7f43df1eb6f0e5146f77282143 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 and flags.
.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\Documents\* | Format-List
FullName : C:\Users\User\OneDrive\Documents\test.txt
Attributes : 5242912
AttributesEx : FILE_ATTRIBUTE_ARCHIVE, FILE_FLAG_OPEN_NO_RECALL, FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS
AttributesHex : 0x00500020
.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.
#>
function Get-FileAttributesEx {
[CmdletBinding()]
param(
[Parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string[]] $Path
)
Set-Strictmode -Version 'Latest'
# List of known Attributes/Flags.
# Note:
# This also can done using [FlagsAttribute()] class instead of Csharp TypeDef
# Refs:
# 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
Add-Type -Language Csharp -TypeDefinition @'
using System;
[FlagsAttribute]
public enum FileAttributesEx : uint {
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, // Undocumented
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 wildcard paths.
foreach ($apath in $Path)
{
# Get-Item finds hidden and system files with -Force, try-catch needed due to -EA not catching all.
try{$apath = Get-Item $apath -Force -ErrorAction SilentlyContinue}catch{}
if ($apath -and (Test-Path $apath))
{
$itemPaths += @($apath | Foreach-Object{$_.FullName})
}
else
{
$itemPaths += $apath
}
}
# Add members to each items we assembled and add AttributesEx and AttributesHex.
# This approach has the benefit
# of returning objects which can be further proessed with these properties,
# as apposed to string output using custom format-list/format-table/select-object commands
foreach ($itempath in $itemPaths)
{
$item = Get-Item $itemPath -Force -ErrorAction:Ignore
# Add properties to $item
$itemAttributesEx = [FileAttributesEx]$item.Attributes.Value__
$itemAttributesHex = '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 $itemAttributesHex
# Return object(s) with a default set of selected properties attached, usually auto-formatted in a wide table.
# Single properties may also be retrieved; Ex. (Get-FileAttributesEx "file").AttributesEx or using Select-Object
$selectItemProperties = @("FullName", "Attributes", "AttributesEx", "AttributesHex")
# Note: If we Format-List here, we only get string output. Better to run this script/function piped to Format-List instead
# e.x. Get-FileAttributesEx .\file | format-list
# Or Get-FileAttributesEx .\Documents\* | format-list -Property fullname,attributesex
#$item | Select-Object -Property $selectItemProperties | Format-List
$item | Select-Object -Property $selectItemProperties
}
}
# If script is called directly with ValueFromPipeLine data; invoke the embedded function with $input piped to it and any args
if ($MyInvocation.ExpectingInput)
{
$input | Get-FileAttributesEx @args
}
# ElseIf script is called directly; invoke the embedded function passing args
elseif (!($MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq ''))
{
Get-FileAttributesEx @args
}
# Else we're being dot-sourced so do nothing.
else {}
# Local Variables:
# mode: PowerShell; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4;
# End:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment