I would like to pass the string name of any Powershell variable to any function requiring a simple -Name parameter string e.g. $anyvar1 as a usable string with value 'anyvar1'. A function will use that variable's name literal var1 in this type of statement, which removes $var1:
param (
[string] $varName
)
try
{
Remove-Variable -Name $varName
}
catch{
# trap any message if the variable doesn't exist
}
}
I need this to be dynamic so if I pass any old variable to a function like this trivial example e.g.
RemoveVar $anyvar1
it will just get the name, not like this where a string literal is used. T
RemoveVar -Name '$anyvar1'
The second approach works, if the $ is stripped off the name literal and so on, but has be constructed.
So any function needing a simple -Name string parameter needs to get that name from the variable $anyvar1 object itself.
Get-Variable requires a simple name to get a variable as an object and thereby access any of its properties, including Name, but the chicken and egg situation occurs.
So a one-liner to get the object name property from any variable is needed. If it is of a particular scope, need to get the scope as well
So,
$Global:anyvar1="SOMEVALUE"
...
...
# all done with $Global:anyvar1
# figure out its name
$varName = Get-VarName -inputObject $Global:anyvar1 ??????
Remove-Variable -Name $varName -Scope Global
# $varName would contain the literal Global:anyvar1.
the function Get-VarName does not exist AFAICT - but there must be a way to
- Create a variable either the simple way or the Set-Variable way
- Use the variable for whatever
- in the above example, get rid of the variable by name when no longer needed etc.
Obviously any locally declared variables, or script level, go out of scope and so on, but $Global variables and others of that sort may need to be explicitly removed.
In C#, I would probably have used nameof(anyvar1) to do this, so something simple like that?
Any help is appreciated. It is probably blindingly obvious but I am not getting it.
Santiago has already provided helpful pointers in the comments; let me elaborate:
PowerShell currently (PowerShell 7.4.x) has no equivalent to C#'s
nameoffeature.$varNameis a reference to the value of the variable namedvarName, and therefore doesn't support reflecting on the variable itself.The only exception is in assignments: in
$varName = ...$varNameindeed identifies the target variable.As an aside: POSIX-compatible shells avoid this ambiguity by requiring that no
$be used in assignments (varName=...).The PowerShell-idiomatic way is indeed to pass the names of variables as a way to identify a variable object for other commands to operate on, via the
*-Variablecmdlets (e.g.Get-VariableandSet-Variable, which of necessity also operate on variable names).Get-Variable -ValueOnly HOMEretrieves the value of the automatic$HOMEvariable, and, likewise, the common-OutVariableparameter expects the name of the output variable as its argument; e.g.,-OutVariable outcaptures the output in variable$out.Therefore, I suggest you use the same approach, in combination with a custom argument-completer to make tab-completion of existing variable names easier.
Windows PowerShell solution, using an
ArgumentCompleterattribute for tab-completion in combination with aValidateScriptfor argument validation:PowerShell (Core) 7+ solution, via a custom
classimplementingIValidateSetValuesGenerator, in combination with theValidateSetattribute, which combines tab-completion with argument validation:Note:
If you type
Invoke-Foo <tab>, the names of existing variables are offered for completion, andInvoke-Foo H<tab>offers all variables whose name starts withH.Additionally, passing the name of a non-existing variable is prevented.