PowerShell - 无法验证参数 'Identity' 的参数。参数为空

PowerShell - Cannot validate argument on parameter 'Identity'. The argument is null

您好,我是 powershell 和 Active Directory 中的新开发脚本,我正在尝试 运行 以下内容。ps1

#! /usr/bin/pwsh

param ([String]$dns, [String]$adminUser, [String]$adminPassword, [String]$user, [String]$newPassword)

$password = ConvertTo-SecureString -String $adminPassword -AsPlainText -Force
$pass = ConvertTo-SecureString -String $newPassword -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($adminUser, $password)
$session = New-PSSession -cn $dns -Credential $credential -Authentication Negotiate
Invoke-Command -Session $session -ScriptBlock {Set-ADAccountPassword -Identity $user -Reset -NewPassword ($pass)}

像这样传递参数

./changePasswordAD.ps1 mydns myuser mypassword userToEdit NewPassword

得到的结果如下

Set-ADAccountPassword: Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.

为什么会发生这种情况,我该如何解决?

提前感谢您的贡献

这是一个 scope problem. A ScriptBlock can't directly reference variables defined in another PowerShell session. New sessions are used when remoting or relying on jobs。 PSRemoting 时 New-PSSessionEnter-PSSession 等的存在和使用暗示了这一点,但在使用作业时并不明显。

您可以像这样在 ScriptBlock 中为变量引用加上 $using: 前缀,以便“使用”在调用会话中定义的变量:

{
  Set-ADAccountPassword -Identity $using:user -Reset -NewPassword $using:pass
}

但是,当 运行在本地系统上安装 ScriptBlock 时,无法使用 using scope。如果您在同一会话中本地执行 ScriptBlock,则引用局部变量 正常工作(通常不使用调用运算符 &Invoke-Command建议在本地使用,因为它不必要地依赖 PSRemoting)。那么,如果我们想让它 运行 任何地方 怎么办?


如果 ScriptBlock 需要无论执行上下文如何都能正常工作,您可以使用 Invoke-Command
-ArgumentList 参数(这也适用于 cmdlet就像 Start-Job 当执行是本地的但在新会话中时)而不是将变量传递到 ScriptBlock:

Invoke-Command -ArgumentList $user, $pass {
  Param( $user, $pass )
  Set-ADAccountPassword -Identity $user -Reset -NewPassword $pass
}

我添加了换行符以提高可读性,但上面的两个 ScriptBlocks 也应该作为一行。

Note: Technically, parameters passed via -ArgumentList would be referenced as $args[0], $args[1], etc. in the order provided such as when processing raw script arguments, but as executing a ScriptBlock functions similarly to a script or... well, function, adding the Param( .... ) bit will cause the arguments provided to be assigned to positional parameters defined in the ScriptBlock; in this case, the friendlier names $user and $pass. The param names do not need to be the same as the original variable names in the parent scope.