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 EnumerateResolvedPaths(bool validateExists = true) { bool isLiteral = MyInvocation.BoundParameters.ContainsKey(nameof(LiteralPath)); Collection 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); } } }