Get-PSOneDirectory.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
function Get-PSOneDirectory
{
  <#
    .SYNOPSIS
    Lists the content of a folder and supports long path names (>256 characters)
 
    .DESCRIPTION
    Uses the Microsoft.Experimental.IO assembly to list folder contents without
    path name length limitations. You can use this function to search for and identify
    files and folders that use long path names.
 
    .EXAMPLE
    Get-PSOneDirectory -Path C:\Windows -ErrorAction SilentlyContinue
    Dumps the entire content of the windows folder and reports all files
    and folders and their path length. Error messages due to folders
    where you have no access permissions are suppressed.
 
    .EXAMPLE
    Get-PSOneDirectory -Path C:\Windows -ErrorAction SilentlyContinue |
      Where-Object PathLength -gt 200
    Lists files and folders with a path length of greater than 200 characters.
    Error messages due to folders where you have no access permissions are suppressed.
 
    .LINK
    https://powershell.one/tricks/assemblies/load-from-memory
    https://github.com/TobiasPSP/Modules.PSOneTools/blob/master/PSOneTools/1.5/Get-PSOneDirectory.ps1
    https://github.com/TobiasPSP/Modules.PSOneTools/blob/master/PSOneTools/1.5/Internal/Install-LongPathSupport.ps1
  #>



    [CmdletBinding()]
    param
    (
        # Folder path to enumerate
        [Parameter(Mandatory)]
        [string]
        $Path
    )

    # load DLL if not loaded yet
    # I am loading the DLL on demand because it is seldom used
    # and should only be loaded when someone wants to run
    # this function:
    & "$PSScriptRoot\Internal\Install-LongPathSupport"

    # emit the path and its length:
    [PSCustomObject]@{
        PathLength = $path.Length
        Type = 'Folder'
        Path = $Path
    }

    # try and enumerate subfolders:
    try
    {
        [Microsoft.Experimental.IO.LongPathDirectory]::EnumerateDirectories($Path) |
        ForEach-Object {
            # recursively enumerate child folders:
            Get-PSOneDirectory -path $_
        }
    }
    catch 
    {
        Write-Error "Unable to open folder '$Path': $_"
    }
    
    # try and enumerate files in folder
    try
    {
        # get all files from current folder:
        [Microsoft.Experimental.IO.LongPathDirectory]::EnumerateFiles($Path) |
        ForEach-Object {
            [PSCustomObject]@{
                PathLength = $_.Length
                Type = 'Folder'
                Path = $_
            }
        }
    }
    catch 
    {
        Write-Error "Unable to open folder '$Path': $_"
    }    
}