我试图弄清楚如何从对象本身获取powershell变量的名称。
之所以这样做,是因为我正在更改通过引用传递给函数的对象,所以我不知道该对象是什么,并且我正在使用Set-Variable cmdlet更改该变量以读取
# .__NEEDTOGETVARNAMEASSTRING is a placeholder because I don't know how to do that.
function Set-ToReadOnly{
param([ref]$inputVar)
$varName = $inputVar.__NEEDTOGETVARNAMEASSTRING
Set-Variable -Name $varName -Option ReadOnly
}
$testVar = 'foo'
Set-ToReadOnly $testVar
我已经浏览了许多类似的问题,但找不到任何能专门回答这个问题的东西。我想完全在函数内部使用变量-我不想依靠传递其他信息。
此外,虽然可能有更简单/更好的设置只读方式,但我一直想知道如何长时间可靠地从变量中提取变量名,所以请着重解决该问题,而不是我的应用程序在此示例中。
答案 0 :(得分:3)
Mathias R. Jessen's helpful answer解释了为什么仅传递其 value 不能可靠地确定原始变量的原因。
解决问题的唯一可靠解决方案是传递变量 object 而不是将其值作为参数:
function Set-ToReadOnly {
param([psvariable] $inputVar) # note the parameter type
$inputVar.Options += 'ReadOnly'
}
$testVar = 'foo'
Set-ToReadOnly (Get-Variable testVar) # pass the variable *object*
如果您的函数在与调用代码相同的范围内定义-如果在不同的模块中定义函数,则 not 为true -您可以更简单地只传递变量 name 并从父级/祖先范围中检索变量:
# Works ONLY when called from the SAME SCOPE / MODULE
function Set-ToReadOnly {
param([string] $inputVarName)
# Retrieve the variable object via Get-Variable.
# This will implicitly look up the chain of ancestral scopes until
# a variable by that name is found.
$inputVar = Get-Variable $inputVarName
$inputVar.Options += 'ReadOnly'
}
$testVar = 'foo'
Set-ToReadOnly testVar # pass the variable *name*
答案 1 :(得分:2)
如in this answer to a similar question所述,您要问的事情(根据变量的值解析身份)无法可靠地完成:
最简单的原因是有关变量的上下文信息 被作为参数参数引用将被剥离 到您可以实际检查内部的参数值时 功能。
在实际调用函数之前,解析器将具有 评估每个参数实参的值,并且 (可选)将所述值的类型强制为任何类型 绑定的参数所期望的。
因此,最终作为参数传递给函数的东西 不是变量$ myVariable,而是(可能强制的)值 $ myVariable。
您可以对引用类型进行的操作只是遍历调用范围中的所有变量,并检查它们是否具有相同的值:
function Set-ReadOnlyVariable {
param(
[Parameter(Mandatory=$true)]
[ValidateScript({ -not $_.GetType().IsValueType })]
$value
)
foreach($variable in Get-Variable -Scope 1 |Where-Object {$_.Value -ne $null -and $_.Value.Equals($value)}){
$variable.Options = $variable.Options -bor [System.Management.Automation.ScopedItemOptions]::ReadOnly
}
}
但是这会将调用者范围内的每个变量都设置为只读,而不仅仅是您引用的变量,我强烈建议您不要使用这种方法-如果您执行了某些操作,那很可能会导致严重错误需要这样做