PowerShell: Increase Default Windows 260-Character Paths Limit

Problem:

Error when trying to rename files manually:
‘The source files name(s) are larger than is supported by the file system…’

Reasons:
  • Parent folder must be less than 248 characters
  • Filename and path must be less than 260 characters
Requirements:

– Windows Management Framework 5.1
– .Net Framework 4.6.2 or more recent
– Windows 10 / Windows server 2016 (Build 1607 or newer)

Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
# This function increases the default windows 260 characters path length limit to 1024
Function remove260CharsPathLimit([string]$computerName=$env:computername){
    $osVersion=[System.Environment]::OSVersion.Version
    $dotNetVersion=(get-itemproperty 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' -Name "Version").Version
    $windowsManagementFramework=$PSVersionTable.PSVersion
    $osFeasible=$osVersion -ge [version]'10.0.1607'
    $dotNetFeasible=$dotNetVersion -ge [version]'4.6.2'
    $windowsFrameworkFeasible=$windowsManagementFramework -ge [version]'5.1'
    if(!$osFeasible){
        write-warning "OS Version $osVersion cannot be registry fixed to work with long file paths"
    }
    if(!$dotNetFeasible){
        write-warning "Dot Net Version $dotNetVersion cannot be registry fixed to work with long file paths"
    }
    if(!$windowsFrameworkFeasible){
        write-warning "Windows Management Framework $windowsManagementFramework cannot be registry fixed to work with long file paths"
    }
    if($osFeasible -and $dotNetFeasible -and $windowsFrameworkFeasible){
        # Declare static variables
        $registryHive="SYSTEM\CurrentControlSet\Control\FileSystem"
        $keyName = 'LongPathsEnabled'
        $value= 1    
        $remoteRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$computerName)
        $currentValue=$remoteRegistry.OpenSubKey("$registryHive\$keyName").GetValue($keyName)
        if($currentValue -ne $value){
            $remoteHive = $remoteRegistry.OpenSubKey($registryHive,$True)
            $remoteHive.CreateSubKey($keyName)
            $remoteKeyValue = $remoteRegistry.OpenSubKey("$registryHive\$keyName",$True)
            $remoteKeyValue.SetValue($keyName,$value)

            # Validation
            $resultKey=$remoteRegistry.OpenSubKey("$registryHive\$keyName")    
            if($resultKey.GetValue($keyName) -eq $value){"\\$computerName\HKLM\$registryHive\$keyName has been added successfully."}
        }else{
            write-host "$computername already has $keyName set as $value" 
        }
        return $true
    }else{
        return $false
    }
}
remove260CharsPathLimit
# This reverses the effects of that previous function
Function restore260CharsPathLimit{
param([string]$computerName=$env:computername)

$registryHive= "SYSTEM\CurrentControlSet\Control\FileSystem"
$keyName = "LongPathsEnabled"
$result=REG DELETE "\\$computerName\HKLM\$registryHive" /v $keyName /f
if($result){"\\$computerName\HKLM\$registryHive\$keyName has been removed successfully."}
}
Other workarounds:
# Older versions of Windows - workaround
$sourceFolder='SourceFolder'
$destinationDirectory='DestinationFolder'
ROBOCOPY $sourceFolder $destinationDirectory /E /w:0 /r:0 /xj /b
ROBOCOPY $sourceFolder $destinationDirectory /E /w:0 /r:0 /xj /b /Copy:S /IS /IT

# save and restore permission
icacls "$sourceFolder" /save C:\ACL_Source /T
icacls "$destinationDirectory" /restore C:\ACL_Source
# Shorten the file name
$filePath='LongFilePathAndName'
$parentFolder=split-path $filePath -parent
$fileName=split-path $filePath -leaf
$removeChars=' ','and','to','&'
$x=$fileName
$truncatedFileName=.{$removeChars|%{$x=$x.Replace($_,'')};$x}
subst x: $parentFolder
rename-item x:\$fileName -NewName $truncatedFileName
cd c:\
subst x: /d

Leave a Reply

Your email address will not be published. Required fields are marked *