尝试使用 Get-ADUser -Filter {displayName

问题描述 投票:0回答:1

我正在使用下面的代码尝试提取 CSV 文件中包含的一组用户的上次登录时间列表。我家里有一个测试域,下面的脚本运行良好。但是,当我在我的工作产品 AD 上尝试它时,出现以下错误。

Get-ADUser: Variable: 'dname' found in expression: $dname is not defined.

这是我整理的脚本。

$list = Import-Csv -Path "C:\data\PowerShell\UserInfo.csv"

ForEach ($user in $list) {
    $dname = $user.Displayname
    Get-ADUser -Filter {displayName -eq $dname} -Properties lastLogon | Select-Object Name, SamAccountName, @{Name="LastLogon"; Expression={[DateTime]::FromFileTime($_.lastLogon)}} | Export-CSV -Path "C:\data\PowerShell\user_last_login.csv" -append -NoTypeInformation
    }
powershell foreach powershell-remoting get-aduser
1个回答
1
投票

tl;博士

出于下一节中解释的原因,您的

Get-ADUser
代理命令[1]
-Filter
参数
中看不到您的局部变量。因此,使用字符串插值来代替,以便直接将变量value合并到
-Filter
参数中(注意需要在扩展值周围使用嵌入式双引号(
`"
)):

Get-ADUser -Filter "displayName -eq `"$dname`"" -Properties lastLogon

顺便说一句:

  • 如果
    -Filter {displayName -eq $dname}
    是直接与 AD 服务器通信的
    Get-ADUser
     模块中的常规(非代理)cmdlet,则 
    ActiveDirectory
    确实可以工作,但 script-block 语法 (
    { ... }
    ) - while方便 - 在概念上存在问题,可能会导致误解,因此
    -Filter 'displayName -eq $name'
    可能更可取 - 请参阅 这个答案 了解背景信息。
    然而,在当前的情况下(隐式远程处理,见下文),使用字符串插值是唯一的解决方案。

背景信息:隐式远程处理的局限性

您的症状意味着 您的 Active Directory 命令是通过 隐式远程处理 提供的,其中本地代理模块用于使用 PowerShell 的 远程处理 功能在幕后将调用中继到远程计算机(代理模块通常是使用Export-PSSession

 cmdlet;本文介绍了隐式远程处理)。

简而言之,代理模块包含与其远程对应项同名的代理命令,采用 PowerShell

functions 的形式,将调用中继到其远程对应项。[1]

虽然这种代理大多按预期工作,但它有

副作用

  • local 变量的引用(例如在 -Filter

     参数中)无法工作
    ,因为最终执行操作的远程命令对本地调用者的变量一无所知。

    • 请注意,AD 模块的

      -Filter

       参数很不寻常,因为它需要一个 
      string,其中可以识别对 PowerShell 变量的引用(仅独立);虽然通常将脚本块{ ... }
      )视为
      -Filter
      参数,但它们实际上在参数绑定期间
      转换为字符串;虽然使用脚本块在语法上方便,但它掩盖了真正的行为(它可能错误地表明参数是一段PowerShell代码,但事实并非如此),并且可能导致概念上的混乱 - 请参阅这个答案了解背景信息。

    • 在将

      actual 脚本块传递给远程处理命令的情况下,特别是在 Invoke-Command

       的上下文中,局部变量的值可以通过 $using:
       作用域嵌入其中。

  • 以下副作用通常适用于脚本模块(

    脚本模块是那些导出的命令作为 PowerShell 函数而不是作为二进制 cmdlet 实现的模块,如隐式远程处理中的情况):

    • 脚本模块不会看到调用者的首选项变量(除非调用恰好是从全局范围进行的,在脚本编写中通常不是这种情况),例如$ErrorActionPreference = 'Stop'
    • 有关详细讨论,请参阅
    • GitHub 问题 #4568
  • 以下副作用不仅适用于一般情况下的 PowerShell

    remoting,还适用于后台 jobs 和“迷你 shell”(使用脚本块的会话中 PowerShell CLI 调用):

    • 重定向、捕获或抑制输出流,除了成功 (1

      ) 和错误输出流 (
      2
      ) 之外,
      不一致支持部分无法重定向和/或捕获流,以及部分无法有效地抑制输出流

    • 有关详细信息,请参阅

      GitHub 问题 #9585


[1] 鉴于 Get-ADUser

 通常是一个 binary cmdlet,测试给定 Get-ADUser
 命令是否是代理命令的一种简单方法是使用 
(Get-Command Get-ADUser).CommandType -eq 'Function'

© www.soinside.com 2019 - 2024. All rights reserved.