我正在使用下面的代码尝试提取 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
}
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
functions 的形式,将调用中继到其远程对应项。[1]
虽然这种代理大多按预期工作,但它有副作用:
对 local 变量的引用(例如在 -Filter
参数中)无法工作,因为最终执行操作的远程命令对本地调用者的变量一无所知。
-Filter
参数很不寻常,因为它需要一个string,其中可以识别对 PowerShell 变量的引用(仅独立);虽然通常将脚本块(
{ ... }
)视为
-Filter
参数,但它们实际上在参数绑定期间转换为字符串;虽然使用脚本块在语法上方便,但它掩盖了真正的行为(它可能错误地表明参数是一段PowerShell代码,但事实并非如此),并且可能导致概念上的混乱 - 请参阅这个答案了解背景信息。
actual 脚本块传递给远程处理命令的情况下,特别是在 Invoke-Command
$using:
作用域嵌入其中。
脚本模块是那些导出的命令作为 PowerShell 函数而不是作为二进制 cmdlet 实现的模块,如隐式远程处理中的情况):
remoting,还适用于后台 jobs 和“迷你 shell”(使用脚本块的会话中 PowerShell CLI 调用):
) 和错误输出流 (
2
) 之外,不一致支持,部分无法重定向和/或捕获流,以及部分无法有效地抑制输出流。
GitHub 问题 #9585。
[1] 鉴于 Get-ADUser
Get-ADUser
命令是否是代理命令的一种简单方法是使用
(Get-Command Get-ADUser).CommandType -eq 'Function'
。