9/19/2023 0 Comments Powershell 5.1 windows 10This is where it gets ugly: In the snippet above, I reset the cached values back to 0, which the internal method (technically actually GetCachedSwitchValueInternal) uses to signify that the value of the switch hasn't been cached, and should be looked up via the public method AppContext.TryGetSwitch. NET tries to be clever and cache the values of these switches, such that if they've ever been accessed already, they're essentially stuck at whatever value they were set to when they were first accessed. Ideally, simply running ::SetSwitch('.UseLegacyPathHandling', $false) should work, except that. Normally, you'd add a line like to your application's " app.config" (to be honest, this probably also works for PowerShell), but if you want to be able to do this at runtime without modifying the system you're on, it turns out to be a pain. The hard bit is then disabling "UseLegacyPathHandling". This then checks an internal boolean, and if this is set to true, it will simply refuse to accept paths longer than 260 characters, even if you use the documented " \\?\" prefix! NET APIs like System.IO.DirectoryInfo call the internal static method System.IO.Path.NormalizePath, which performs initial validation of the file path you supply. ::GetType('System.AppContextSwitches').GetField('_blockLongPaths', ::Static -bor ::NonPublic).SetValue($null, 0)Īfter poking around at a decompiled view of " C:\Windows\Microsoft.NET\Framework64\v9\mscorlib.dll" in ILSpy for a couple of hours, I determined that. ::GetType('System.AppContextSwitches').GetField('_useLegacyPathHandling', ::Static -bor ::NonPublic).SetValue($null, 0) Run the following in your current PowerShell session or prepend it in your scripts (this may not work in future versions of PowerShell/NET, as it uses internal and undocumented APIs): ::SetSwitch('.UseLegacyPathHandling', $false) I posted this question purely because I figured out a good answer, that doesn't require loading native Win32 DLLs via P/Invoke, doesn't require setting any registry keys, doesn't require falling back to calling any native executables, and appears to work all the way back to Windows Server 2012R2 (I don't have anything older to test on). I'd expect PowerShell/.NET to accept long paths when I prepend " \\?\", but it still insists that the path is too long, even though the below-linked Microsoft article suggests that this should work: In Windows Server 2016 and Windows 10, I seem to be able to get around this by setting the DWORD " LongPathsEnabled" to 1 under the registry key " HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem", but this doesn't work for systems in our environment running older versions of Windows or PowerShell. When I attempt to bypass this limitation by prepending " \\?\", it simply doesn't return anything at all, and if I instead try to look up the directory with, I get the same "too long" error as before. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.". The switch to "pwsh.exe" happened at some point pretty early in development, but PSCore had been around for a while already.When using PowerShell 5.1 and earlier in Windows and trying the list the contents of a folder using the Get-ChildItem command - where the folder path is longer than 260 characters - results in an " ItemNotFoundException" or the error " The specified path, file name, or both are too long. PS C:\Program Files\PowerShell\6> $()Īlso beware of older PowerShell Core versions with the executable name "powershell.exe" (confusingly the same as Windows PowerShell). PS C:\Program Files\PowerShell\6> ls pwsh.* PS C:\> cd (Split-Path -Parent (Get-Command -Name pwsh).Path) To find where the PowerShell Core executable is, if it's installed, you can, if it's in $Env:Path, use the command:
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |