diff --git a/CHANGELOG.md b/CHANGELOG.md index 67f741b..6d6048a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -272,7 +272,8 @@ The format is based on - Fix `Test-Path2`, which stopped with the terminating error "Illegal characters in path" in Windows PowerShell for a path with a character that Windows doesn't allow in names, such as `|`; it now returns `$false` - for such a path, as in PowerShell 7 + for such a path, as in PowerShell 7, and writes the reason as a debug + message - Fix the cmdlets that enable the Backup, Restore, Take Ownership, and Security privileges, which left them enabled in the session when a later command, such as `Select-Object -First`, or a terminating error stopped diff --git a/Docs/Cmdlets/Test-Path2.md b/Docs/Cmdlets/Test-Path2.md index bf28c32..5b47fc5 100644 --- a/Docs/Cmdlets/Test-Path2.md +++ b/Docs/Cmdlets/Test-Path2.md @@ -117,7 +117,7 @@ For each path, the cmdlet writes `$true` when the item exists and matches `-Path The cmdlet resolves paths through the AlphaFS library, which is not bound by the 260-character `MAX_PATH` limit of the Windows PowerShell file system provider. Use `Test-Path2` instead of `Test-Path` when a path can be longer than that limit. -A path that does not exist is not an error condition. The cmdlet writes `$false` and continues with the next path. This also applies to a path with a character that Windows doesn't allow in names, such as `|` or `<`; before 5.0.0, such a path stopped the cmdlet with the terminating error "Illegal characters in path" in Windows PowerShell. +A path that does not exist is not an error condition. The cmdlet writes `$false` and continues with the next path. This also applies to a path with a character that Windows doesn't allow in names, such as `|` or `<`; Windows PowerShell rejects such a path, and the cmdlet writes the reason as a debug message. Before 5.0.0, such a path stopped the cmdlet with the terminating error "Illegal characters in path" in Windows PowerShell. ## RELATED LINKS diff --git a/NTFSSecurity/PathCmdlets/TestPath2.cs b/NTFSSecurity/PathCmdlets/TestPath2.cs index b087a2b..5d7c0eb 100644 --- a/NTFSSecurity/PathCmdlets/TestPath2.cs +++ b/NTFSSecurity/PathCmdlets/TestPath2.cs @@ -45,42 +45,51 @@ namespace NTFSSecurity { foreach (var path in paths) { + FileSystemInfo item = null; try { - FileSystemInfo item; TryGetFileSystemInfo2(path, out item); - - if (item == null) - WriteObject(false); - else - { - if (PathType == TestPathType.Any) - WriteObject(true); - else if (PathType == TestPathType.Container & item is DirectoryInfo) - WriteObject(true); - else if (PathType == TestPathType.Leaf & item is FileInfo) - WriteObject(true); - else - WriteObject(false); - } } catch (System.IO.FileNotFoundException ex) { WriteError(new ErrorRecord(ex, "PathNotFound", ErrorCategory.ObjectNotFound, path)); + continue; } // In Windows PowerShell, .NET rejects a path with a character that Windows doesn't allow in names. // Such an item can't exist, so the cmdlet writes $false, as in PowerShell 7 and like Test-Path. - catch (System.ArgumentException) + catch (System.ArgumentException ex) { - WriteObject(false); + WriteInvalidPath(path, ex); + continue; } - catch (System.NotSupportedException) + catch (System.NotSupportedException ex) { + WriteInvalidPath(path, ex); + continue; + } + + if (item == null) WriteObject(false); + else + { + if (PathType == TestPathType.Any) + WriteObject(true); + else if (PathType == TestPathType.Container & item is DirectoryInfo) + WriteObject(true); + else if (PathType == TestPathType.Leaf & item is FileInfo) + WriteObject(true); + else + WriteObject(false); } } } + private void WriteInvalidPath(string path, System.Exception exception) + { + WriteDebug(string.Format("'{0}' is not a valid path: {1}", path, exception.Message)); + WriteObject(false); + } + protected override void EndProcessing() { base.EndProcessing(); diff --git a/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml b/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml index fd2befb..9dec184 100644 --- a/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml +++ b/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml @@ -10136,7 +10136,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd The cmdlet resolves paths through the AlphaFS library, which is not bound by the 260-character `MAX_PATH` limit of the Windows PowerShell file system provider. Use `Test-Path2` instead of `Test-Path` when a path can be longer than that limit. - A path that does not exist is not an error condition. The cmdlet writes `$false` and continues with the next path. This also applies to a path with a character that Windows doesn't allow in names, such as `|` or `<`; before 5.0.0, such a path stopped the cmdlet with the terminating error "Illegal characters in path" in Windows PowerShell. + A path that does not exist is not an error condition. The cmdlet writes `$false` and continues with the next path. This also applies to a path with a character that Windows doesn't allow in names, such as `|` or `<`; Windows PowerShell rejects such a path, and the cmdlet writes the reason as a debug message. Before 5.0.0, such a path stopped the cmdlet with the terminating error "Illegal characters in path" in Windows PowerShell. diff --git a/Tests/ItemCmdlets.Tests.ps1 b/Tests/ItemCmdlets.Tests.ps1 index cfd91df..ae29a04 100644 --- a/Tests/ItemCmdlets.Tests.ps1 +++ b/Tests/ItemCmdlets.Tests.ps1 @@ -319,6 +319,22 @@ Describe 'Test-Path2' { $testErrors | Should -BeNullOrEmpty $result -join ',' | Should -Be 'False,True' } + + # PowerShell 7 accepts these characters and finds no item, so only Windows PowerShell rejects the path. Before + # 5.0.0-rc6, the cmdlet wrote $false for a rejected path without saying why. -Debug would prompt in Windows + # PowerShell, so the test sets the preference. + It 'Should say in a debug message why it writes $false for a path that Windows PowerShell rejects' -Skip:($PSVersionTable.PSEdition -ne 'Desktop') { + $invalid = Join-Path -Path $folder -ChildPath 'a|b' + $DebugPreference = 'Continue' + + $output = @(Test-Path2 -Path $invalid -ErrorAction Stop 5>&1) + + $messages = @($output | Where-Object -FilterScript { $_ -is [Management.Automation.DebugRecord] } | + Where-Object -Property Message -Like -Value '*is not a valid path*') + $messages | Should -HaveCount 1 + $messages[0].Message.Contains("'$invalid'") | Should -BeTrue + $output | Where-Object -FilterScript { $_ -is [bool] } | Should -BeFalse + } } Describe 'Get-DiskSpace' {