|
// Source - https://stackoverflow.com/a/79911456 |
|
// Posted by Santiago Squarzon, modified by community. See post 'Timeline' for change history |
|
// Retrieved 2026-03-20, License - CC BY-SA 4.0 |
|
|
|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using System.IO; |
|
using System.Management.Automation; |
|
using System.Management.Automation.Provider; |
|
|
|
[CmdletProvider(ProviderName, ProviderCapabilities.None)] |
|
public class CustomVariableProvider : ContainerCmdletProvider, IContentCmdletProvider |
|
{ |
|
internal const string ProviderName = "CustomVariable"; |
|
|
|
private Dictionary<string, object?>? _variables; |
|
|
|
private Dictionary<string, object?> Variables { get => _variables ??= ((CustomVariableDrive)PSDriveInfo).Variables; } |
|
|
|
private sealed class CustomVariableDrive(PSDriveInfo driveInfo) : PSDriveInfo(driveInfo) |
|
{ |
|
internal Dictionary<string, object?> Variables { get; } = new(StringComparer.OrdinalIgnoreCase); |
|
} |
|
|
|
private sealed class CustomVariableHandler(Dictionary<string, object?> vars, string key) |
|
: IContentReader, IContentWriter |
|
{ |
|
private bool _read; |
|
|
|
public void Close() { } |
|
|
|
public void Dispose() { } |
|
|
|
public IList Read(long readCount) |
|
{ |
|
if (_read) return Array.Empty<object>(); |
|
|
|
_read = true; |
|
object? value = vars[key]; |
|
return LanguagePrimitives.ConvertTo<object[]>( |
|
value switch |
|
{ |
|
PSObject { BaseObject: ScriptBlock sb } => sb.InvokeReturnAsIs(), |
|
ScriptBlock sb => sb.InvokeReturnAsIs(), |
|
_ => value |
|
}); |
|
} |
|
|
|
public void Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); |
|
|
|
public IList Write(IList content) |
|
{ |
|
vars[key] = content is { Count: 1 } ? content[0] : content; |
|
return content; |
|
} |
|
} |
|
|
|
private static string NormalizePath(string path) => |
|
string.IsNullOrEmpty(path) ? string.Empty : path.Trim('\\', '/'); |
|
|
|
protected override PSDriveInfo NewDrive(PSDriveInfo drive) => new CustomVariableDrive(drive); |
|
|
|
private KeyValuePair<string, object?> GetKeyValue(string path) => new(path, Variables[path]); |
|
|
|
protected override bool ItemExists(string path) |
|
{ |
|
string normalized = NormalizePath(path); |
|
return string.IsNullOrEmpty(normalized) || Variables.ContainsKey(normalized); |
|
} |
|
|
|
protected static bool IsItemContainer(string path) => string.IsNullOrEmpty(NormalizePath(path)); |
|
|
|
protected override void GetChildItems(string path, bool recurse) |
|
{ |
|
string normalized = NormalizePath(path); |
|
|
|
if (string.IsNullOrEmpty(normalized)) |
|
{ |
|
foreach (KeyValuePair<string, object?> kvp in Variables) |
|
WriteItemObject(kvp, kvp.Key, false); |
|
|
|
return; |
|
} |
|
|
|
WriteItemObject(GetKeyValue(normalized), normalized, false); |
|
} |
|
|
|
protected override void GetItem(string path) |
|
{ |
|
string normalized = NormalizePath(path); |
|
|
|
if (string.IsNullOrEmpty(normalized)) |
|
{ |
|
WriteItemObject(Variables, normalized, true); |
|
return; |
|
} |
|
|
|
WriteItemObject(GetKeyValue(normalized), normalized, false); |
|
} |
|
|
|
protected override bool IsValidPath(string path) => true; |
|
|
|
protected override string[] ExpandPath(string path) => [NormalizePath(path)]; |
|
|
|
protected override void SetItem(string path, object value) => |
|
Variables[NormalizePath(path)] = value; |
|
|
|
protected override void NewItem(string path, string itemTypeName, object newItemValue) |
|
{ |
|
string normalized = NormalizePath(path); |
|
// Will throw "An item with the same key has already been added. ..." |
|
Variables.Add(normalized, newItemValue); |
|
WriteItemObject(GetKeyValue(normalized), normalized, false); |
|
} |
|
|
|
public IContentReader GetContentReader(string path) => |
|
new CustomVariableHandler(Variables, NormalizePath(path)); |
|
|
|
public object? GetContentReaderDynamicParameters(string path) => null; |
|
|
|
public IContentWriter GetContentWriter(string path) => |
|
new CustomVariableHandler(Variables, NormalizePath(path)); |
|
|
|
public object? GetContentWriterDynamicParameters(string path) => null; |
|
|
|
public void ClearContent(string path) |
|
{ |
|
string normalized = NormalizePath(path); |
|
if (Variables.ContainsKey(normalized)) |
|
Variables[normalized] = null; |
|
} |
|
|
|
public object? ClearContentDynamicParameters(string path) => null; |
|
} |