Skip to content

Instantly share code, notes, and snippets.

@santisq
Last active February 11, 2025 00:50
Show Gist options
  • Save santisq/a24d9f02aa40c4bc7fa23a1962c8c4e2 to your computer and use it in GitHub Desktop.
Save santisq/a24d9f02aa40c4bc7fa23a1962c8c4e2 to your computer and use it in GitHub Desktop.
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