简体   繁体   English

从实际变量中获取powershell变量名

[英]get powershell variable name from actual variable

I am trying to figure out how to get the name of a powershell variable from the object, itself. 我试图弄清楚如何从对象本身获取powershell变量的名称。

I'm doing this because I'm making changes to an object passed by reference into a function, so I don't know what the object will be and I am using the Set-Variable cmdlet to change that variable to read only. 我这样做是因为我正在对通过引用传递给函数的对象进行更改,所以我不知道对象是什么,我使用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

I've looked through a lot of similar questions and can't find anything that answers this specifically. 我查看了很多类似的问题,找不到任何具体的答案。 I want to work with the variable entirely inside of the function--I don't want to rely on passing in additional information. 我想完全在函数内部使用变量 - 我不想依赖传递其他信息。

Also, while there may be easier/better ways of setting read-only, I have been wanting to know how to reliably pull the variable name from a variable for a long time, so please focus solving that problem, not my application of it in this example. 此外,虽然可能有更容易/更好的方式设置只读,我一直想知道如何可靠地从变量中提取变量名称,所以请集中解决这个问题,而不是我的应用程序这个例子。

Mathias R. Jessen's helpful answer explains why the originating variable cannot be reliably determined if you only pass its value . Mathias R. Jessen的有用答案解释了为什么如果只传递其值,则无法可靠地确定原始变量。

The only robust solution to your problem is to pass a variable object rather than its value as an argument : 对您的问题唯一可靠的解决方案是传递变量对象而不是其值作为参数

function Set-ToReadOnly {
  param([psvariable] $inputVar) # note the parameter type
  $inputVar.Options += 'ReadOnly'
}

$testVar = 'foo'
Set-ToReadOnly (Get-Variable testVar) # pass the variable *object*

If your function is defined in the same scope as the calling code - which is not true if you the function is defined in a (different) module - you can more simply pass just the variable name and retrieve the variable from the parent / an ancestral scope: 如果你的函数定义在与调用代码相同的范围内 - 如果你在(不同的) 模块中定义了函数,则不是这样 - 你可以更简单地传递变量并从父/祖先中检索变量范围:

# 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*

As noted in this answer to a similar question , what you're asking (resolving the identity of a variable based on its value) can not be done reliably: 正如对类似问题的回答所述 ,您所要求的(根据其值解析变量的身份)无法可靠地完成:

The simple reason being that contextual information about a variable being referenced as a parameter argument will have been stripped away by the time you can actually inspect the parameter value inside the function. 简单的原因是,当您实际检查函数内的参数值时,有关被引用为参数参数的变量的上下文信息将被剥离。

Long before the function is actually called, the parser will have evaluated the value of every single parameter argument, and (optionally) coerced the type of said value to whatever type is expected by the parameter it's bound to. 在实际调用函数之前很久,解析器将评估每个参数参数的值,并且(可选地)将所述值的类型强制转换为它所绑定的参数所期望的任何类型。

So the thing that is ultimately passed as an argument to the function is not the variable $myVariable, but the (potentially coerced) value of $myVariable. 所以最终作为参数传递给函数的东西不是变量$ myVariable,而是$ myVariable的(可能强制的)值。

What you could do for reference types is simply go through all variables in the calling scope and check if they have the same value: 可以为引用类型执行的操作只是遍历调用范围中的所有变量,并检查它们是否具有相同的值:

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
  }
}

But this will set every single variable in the callers scope with that value to readonly, not just the variable you referenced, and I'd strongly recommend against this kind of thing - you're most likely doing something horribly wrong if you need to do this 但是这会将调用者范围中的每个变量设置为只读取该值,而不仅仅是您引用的变量,我强烈建议不要这样做 - 如果你需要做的话,你很可能会做一些可怕的错误这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM