Last active
February 11, 2025 00:50
-
-
Save santisq/a24d9f02aa40c4bc7fa23a1962c8c4e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.ComponentModel; | |
using System.IO; | |
using System.Management.Automation; | |
using Microsoft.PowerShell.Commands; | |
[EditorBrowsable(EditorBrowsableState.Never)] | |
public abstract class CmdletWithPathBase : PSCmdlet | |
{ | |
private string[]? _paths; | |
[Parameter( | |
Position = 0, | |
ValueFromPipeline = true, | |
ValueFromPipelineByPropertyName = true, | |
ParameterSetName = "Path")] | |
[SupportsWildcards] | |
[ValidateNotNullOrEmpty] | |
public virtual string[]? Path | |
{ | |
get => _paths; | |
set => _paths = value; | |
} | |
[Parameter( | |
ValueFromPipelineByPropertyName = true, | |
ParameterSetName = "LiteralPath")] | |
[Alias("PSPath")] | |
[ValidateNotNullOrEmpty] | |
public virtual string[]? LiteralPath | |
{ | |
get => _paths; | |
set => _paths = value; | |
} | |
protected IEnumerable<string> EnumerateResolvedPaths(bool validateExists = true) | |
{ | |
bool isLiteral = MyInvocation.BoundParameters.ContainsKey(nameof(LiteralPath)); | |
Collection<string> resolvedPaths; | |
ProviderInfo provider; | |
foreach (string path in _paths ?? [SessionState.Path.CurrentFileSystemLocation.Path]) | |
{ | |
if (isLiteral) | |
{ | |
string resolved = SessionState.Path | |
.GetUnresolvedProviderPathFromPSPath(path, out provider, out _); | |
if (!WriteErrorIfInvalidProvider(resolved, provider) && | |
!WriteErrorIfNotExists(resolved, validateExists)) | |
{ | |
yield return resolved; | |
} | |
continue; | |
} | |
try | |
{ | |
resolvedPaths = GetResolvedProviderPathFromPSPath(path, out provider); | |
} | |
catch (Exception exception) | |
{ | |
WriteError(new ErrorRecord( | |
exception, "ResolvePath", ErrorCategory.ObjectNotFound, path)); | |
continue; | |
} | |
foreach (string resolvedPath in resolvedPaths) | |
{ | |
if (WriteErrorIfInvalidProvider(resolvedPath, provider)) | |
{ | |
continue; | |
} | |
yield return resolvedPath; | |
} | |
} | |
} | |
private bool WriteErrorIfInvalidProvider(string path, ProviderInfo provider) | |
{ | |
if (provider.ImplementingType == typeof(FileSystemProvider)) | |
{ | |
return false; | |
} | |
ArgumentException ex = new($"The resolved path '{path}' is not a FileSystem path but '{provider.Name}'."); | |
WriteError(new ErrorRecord(ex, "InvalidProvider", ErrorCategory.InvalidArgument, path)); | |
return true; | |
} | |
private bool WriteErrorIfNotExists(string path, bool validateExists) | |
{ | |
if (!validateExists) | |
{ | |
return false; | |
} | |
if (File.Exists(path) || Directory.Exists(path)) | |
{ | |
return false; | |
} | |
ItemNotFoundException ex = new($"Cannot find path '{path}' because it does not exist."); | |
WriteError(new ErrorRecord(ex, "InvalidPath", ErrorCategory.InvalidArgument, path)); | |
return true; | |
} | |
} | |
[Cmdlet( | |
VerbsDiagnostic.Test, "PathCommand", | |
DefaultParameterSetName = "Path")] | |
public sealed class TestPathCommand : CmdletWithPathBase | |
{ | |
protected override void ProcessRecord() | |
{ | |
foreach (string path in EnumerateResolvedPaths()) | |
{ | |
WriteObject(path); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment