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-PSSession
、Enter-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.
您好,我是 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-PSSession
、Enter-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 aScriptBlock
functions similarly to a script or... well, function, adding theParam( .... )
bit will cause the arguments provided to be assigned to positional parameters defined in theScriptBlock
; in this case, the friendlier names$user
and$pass
. Theparam
names do not need to be the same as the original variable names in the parent scope.