使用基于括号的 -Filter 参数时,为什么 $PSItem 没有按预期运行? [英] Why doesn't $PSItem behave as expected when using a bracket-based -Filter argument?

查看:17
本文介绍了使用基于括号的 -Filter 参数时,为什么 $PSItem 没有按预期运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在帮助用户解决这个问题,链接到我的回答:仅使用电子邮件地址将用户从 .csv 添加到 A/D 组的 Powershell 脚本?

I was assisting a user with this question, linked to my answer here: Powershell script to add users to A/D group from .csv using email address only?

最初我按如下方式编写脚本,对 Get-AdUser 使用基于括号的过滤器,如下所示:

Initially I wrote the script as follows, using a bracket-based filter for Get-AdUser like follows:

Import-CSV "C:usersBalbahagwdesktop	est1.csv" | 
  Foreach-Object {

    # Here, $_.EmailAddress refused to resolve
    $aduser = Get-ADUser -Filter { EmailAddress -eq $_.EmailAddress }

    if( $aduser ) {
      Write-Output "Adding user $($aduser.SamAccountName) to groupname"
      Add-ADGroupMember -Identity groupname -Members $aduser
    } else {
      Write-Warning "Could not find user in AD with email address $($_.EmailAddress)"
    }
  }

但是,$_.EmailAddress 未能填充值.但是,将 Get-ADUser 过滤器更改为基于字符串的过滤器可以按预期工作:

However, $_.EmailAddress failed to populate a value. However, changing the Get-ADUser filter to a string-based filter worked as intended:

$aduser = Get-ADUser -Filter "EmailAddress -eq '$($_.EmailAddress)'"

我正在经历什么奇怪的事情,为什么?是不是因为当我使用方括号时,它被视为一个新范围并且 $PSItem 不会跟随?

What is the strangeness I'm experiencing, and why? Is it because when I'm using brackets, it's treated as a new scope and the $PSItem won't follow?

推荐答案

  • -Filter 参数一般是string 参数(用
    验证Get-Help Get-AdUser -Parameter Filter)

    • -Filter parameters are generally string parameters (verify with
      Get-Help Get-AdUser -Parameter Filter)

      • 他们通常接受PowerShell代码 - 过滤器是提供者特定的并且通常有自己的语法,尽管它恰好是PowerShell-类似,就 AD cmdlet 而言.
        此外,他们通常不了解 PowerShell 变量(见下文).
      • They generally do not accept PowerShell code - filters are provider-specific and often have their own syntax, although it happens to be PowerShell-like in the case of the AD cmdlets.
        Also, they generally have no knowledge of PowerShell variables (see below).

      因此,当一个脚本块 ({ ... }) 被传递时,它被转换成一个字符串,其计算结果为它的 literal 内容(开始 { 和结束 } 之间的所有内容):

      Thus, when a script block ({ ... }) is passed, it is converted to a string, which evaluates to its literal contents (everything between the opening { and the closing }):

      • { EmailAddress -eq $_.EmailAddress }.ToString() 产生文字字符串 EmailAddress -eq $_.EmailAddress - 没有任何评估 - 和这就是 Get-AdUser 看到的 - 没有评估发生.

      • { EmailAddress -eq $_.EmailAddress }.ToString() yields the literal string EmailAddress -eq $_.EmailAddress - without any evaluation - and that's what Get-AdUser sees - no evaluation takes place.

      为了支持将脚本块传递给 AD cmdlet 的 -Filter 参数的广泛但不明智的做法,可能是善意但被误导的努力,似乎这些 cmdlet实际上显式地扩展简单变量引用,例如在它们接收的字符串文字中$_,但这不适用于表达式,例如访问一个变量的属性 ($_.EmailAddress)

      In a presumably well-meaning but misguided effort to support the widespread, but ill-advised practice of passing script blocks to the -Filter parameter of AD cmdlets, it seems that these cmdlets actually explicitly expand simple variable references such as $_ in the string literal they receive, but that doesn't work with expressions, such as accessing a property of a variable ($_.EmailAddress)

      因此,-Filter 参数通常应该作为可扩展字符串 ("...");在手头的情况下:

      Therefore, -Filter arguments should generally be passed as expandable strings ("..."); in the case at hand:

       -Filter  "EmailAddress -eq '$($_.EmailAddress)'"
      

      也就是说,唯一可靠的解决方案是使用 strings 和可变部分 烘焙预先,通过字符串扩展,如如上所示.

      That is, the only robust solution is to use strings with the variable parts baked in, up front, via string expansion, as shown above.

      对于既不是数字也不是字符串的值,例如日期,您可能必须使用文字字符串('...') 并依赖 AD 提供者评估对 PowerShell 变量的简单引用的能力(例如,$date) - 请参阅 我的这个答案 了解详情.

      For values that are neither numbers nor strings, such as dates, you may have to use a literal string ('...') and rely on the AD provider's ability to evaluate simple references to PowerShell variables (e.g., $date) - see this answer of mine for details.

      如前所述,AD 过滤器的语法只是 PowerShell-like:它仅支持 PowerShell 支持的运算符的子集,而受支持的运算符在行为上略有不同 - 请参阅 获取帮助 about_ActiveDirectory_Filter.

      As stated, the syntax of AD filters is only PowerShell-like: it supports only a subset of the operators that PowerShell supports and those that are supported differ subtly in behavior - see Get-Help about_ActiveDirectory_Filter.

      • 使用脚本块很诱人,因为里面的代码不需要转义嵌入的引号/不需要引号字符的交替,也不需要使用子表达式运算符 $(...).然而,除了使用脚本块作为字符串通常效率低下之外,这里的问题是脚本块做出了它无法兑现的承诺:它看起来像你'重新传递一段 PowerShell 代码,但你没有 - 它只在简单的情况下有效(然后只是由于上面提到的误导性适应);一般来说,很难记住它在什么情况下不起作用以及如果它失败了如何使它工作.

      • It is tempting to use script blocks, because the code inside requires no escaping of embedded quotes / no alternating of quote chars and no use of subexpression operator $(...). However, aside from using script blocks as strings being inefficient in general, the problem here is that the script block is making a promise that it cannot keep: it looks like you're passing a piece of PowerShell code, but you're not - and it works only in simple cases (and then only due to the misguided accommodation mentioned above); generally, it's hard to remember under what circumstances it doesn't work and how to make it work if it fails.

      因此很遗憾官方文档在其示例中使用了脚本块.

      It is therefore really unfortunate that the official documentation uses script blocks in its examples.

      有关更全面的讨论,请参阅我的这个答案.

      For a more comprehensive discussion, see this answer of mine.

      这篇关于使用基于括号的 -Filter 参数时,为什么 $PSItem 没有按预期运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆