【问题标题】:get powershell variable name from actual variable从实际变量中获取 powershell 变量名
【发布时间】:2018-12-20 01:22:39
【问题描述】:

我试图弄清楚如何从对象本身获取 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

我查看了很多类似的问题,但找不到任何可以具体回答的问题。我想完全在函数内部使用变量——我不想依赖传递额外的信息。

另外,虽然设置只读可能有更简单/更好的方法,但我一直想知道如何可靠地从变量中提取变量名,所以请专注于解决这个问题,而不是我的应用程序在这个例子中。

【问题讨论】:

标签: powershell variables pass-by-reference readonly variable-names


【解决方案1】:

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

但这会将调用者作用域中具有该值的每个变量设置为只读,而不仅仅是您引用的变量,我强烈建议您不要这样做 - 如果您这样做,您很可能会做一些可怕的错误需要这样做

【讨论】:

    【解决方案2】:

    Mathias R. Jessen's helpful answer 解释了为什么如果你只传递它的 就不能可靠地确定原始变量。

    解决您的问题的唯一稳健方法是传递一个变量对象而不是其值作为参数

    function Set-ToReadOnly {
      param([psvariable] $inputVar) # note the parameter type
      $inputVar.Options += 'ReadOnly'
    }
    
    $testVar = 'foo'
    Set-ToReadOnly (Get-Variable testVar) # pass the variable *object*
    

    如果您的函数定义在与调用代码相同的范围内 - 如果您的函数定义在(不同的)模块中,则 不是 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*
    

    【讨论】:

      猜你喜欢
      • 2016-12-18
      • 1970-01-01
      • 2013-11-07
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多