在 Invoke-Command Powershell 命令的 -ScriptBlock 中使用参数调用函数
Call function with arguments in -ScriptBlock of Invoke-Command Powershell command
我有两台服务器,其中一台是 Active Directory,另一台是 Windows10。
我想编写一个删除和创建目录的 Powershell 脚本。(为了简单的情况,我选择删除和创建目录,但实际上,该脚本用于获取活动目录的组和组织单元。)
我写了三个函数和下面的 Powershell 脚本。第一个用于远程服务器上的 运行 命令,其中两个用于创建和删除目录。 my_powershell_script.ps1
Param($choosen_function, $username, $password, $remote_address, $absolute_path)
function run_commend_on_remote_server {
param ($choosen_function, $username, $password, $remote_address)
$secpsw = $password | ConvertTo-SecureString -AsPlainText -Force
$credobject = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $secpsw
$psrs = New-PSSession -Credential $credobject -ComputerName $remote_address
Enter-PSSession $psrs
Invoke-Command -ScriptBlock {$choosen_function -absolute_path $absolute_path} -Session $psrs
Exit-PSSession
Remove-PSSession $psrs
}
function delete_directory{
param($absolute_path)
Remove-Item $absolute_path -Recurse
}
function make_directory{
param($absolute_path)
mkdir $absolute_path
}
run_commend_on_remote_server -choosen_function $choosen_function -username $username -password $password -remote_address $remote_address -absolute_path $absolute_path
当我 运行 这个脚本如下时,我得到了错误:
my_powershell_script.ps1 -choosen_function make_directory -username admin -password admin -remote_address 192.168.2.22
为了使该脚本正常工作,需要更改一些内容。
- 在您的
run_commend_on_remote_server
函数中,您使用的是用于交互式会话的 Enter-PSSession
,然后您使用的是 Invoke-Command
,在这种情况下,如果我理解您的意图正确 Enter-PSSession
必须删除。
- 在同一函数中,在
Invoke-Command
脚本块的内部,正在使用 $choosen_function
,但是尚未在该范围内定义 2 个辅助函数(remote scope). You need to pass the definition of your functions if you want to use them remotely. Same thing applies for $absolute_path
. In order to pass locally defined variables into the remote scope, you can use either -ArgumentList
or $using:
, see Example 9 来自 Invoke-Command
博士
The command uses the Using
scope modifier to identify a local variable in a remote command. By default, all variables are assumed to be defined in the remote session. The Using
scope modifier was introduced in PowerShell 3.0.
- 由于你想要运行的辅助函数的名称存储在一个变量中,为了执行它,您需要使用 call operator
&
or the dot sourcing operator .
来调用它,即:& $choosen_function
.
- 与其将
UserName
和 Password
作为脚本的参数传递,我个人建议您在脚本中调用 Get-Credential
。
-absolute_path
被用作 run_commend_on_remote_server
的参数,但函数没有这样的参数。
理解了这些要点后,您可以通过以下方式处理脚本:
[cmdletbinding()]
param(
[ValidateSet('delete_directory', 'make_directory')]
$choosen_function,
$remote_address,
$absolute_path
)
function delete_directory{
# code here
}
function make_directory{
# code here
}
# store both function's definition, this will be used
# to pass them to the remote scope
$def = @(
${function:delete_directory}.ToString()
${function:make_directory}.ToString()
)
function run_commend_on_remote_server {
param ($choosen_function, $remote_address, $Credential, $absolute_path)
Invoke-Command -ScriptBlock {
# bring the definition of both functions to this scope
$deldir, $makedir = $using:def
# define both functions
${function:delete_directory} = $deldir
${function:make_directory} = $makedir
# invoke the chosen function
& $using:choosen_function -absolute_path $using:absolute_path
} -Credential $Credential -ComputerName $remote_address
}
# Here we call Get-Credential to get the pop-up for username and secure password
$cred = Get-Credential
$params = @{
choosen_function = $choosen_function
credential = $cred
remote_address = $remote_address
absolute_path = $absolute_path
}
run_commend_on_remote_server @params
我有两台服务器,其中一台是 Active Directory,另一台是 Windows10。 我想编写一个删除和创建目录的 Powershell 脚本。(为了简单的情况,我选择删除和创建目录,但实际上,该脚本用于获取活动目录的组和组织单元。)
我写了三个函数和下面的 Powershell 脚本。第一个用于远程服务器上的 运行 命令,其中两个用于创建和删除目录。 my_powershell_script.ps1
Param($choosen_function, $username, $password, $remote_address, $absolute_path)
function run_commend_on_remote_server {
param ($choosen_function, $username, $password, $remote_address)
$secpsw = $password | ConvertTo-SecureString -AsPlainText -Force
$credobject = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $secpsw
$psrs = New-PSSession -Credential $credobject -ComputerName $remote_address
Enter-PSSession $psrs
Invoke-Command -ScriptBlock {$choosen_function -absolute_path $absolute_path} -Session $psrs
Exit-PSSession
Remove-PSSession $psrs
}
function delete_directory{
param($absolute_path)
Remove-Item $absolute_path -Recurse
}
function make_directory{
param($absolute_path)
mkdir $absolute_path
}
run_commend_on_remote_server -choosen_function $choosen_function -username $username -password $password -remote_address $remote_address -absolute_path $absolute_path
当我 运行 这个脚本如下时,我得到了错误:
my_powershell_script.ps1 -choosen_function make_directory -username admin -password admin -remote_address 192.168.2.22
为了使该脚本正常工作,需要更改一些内容。
- 在您的
run_commend_on_remote_server
函数中,您使用的是用于交互式会话的Enter-PSSession
,然后您使用的是Invoke-Command
,在这种情况下,如果我理解您的意图正确Enter-PSSession
必须删除。 - 在同一函数中,在
Invoke-Command
脚本块的内部,正在使用$choosen_function
,但是尚未在该范围内定义 2 个辅助函数(remote scope). You need to pass the definition of your functions if you want to use them remotely. Same thing applies for$absolute_path
. In order to pass locally defined variables into the remote scope, you can use either-ArgumentList
or$using:
, see Example 9 来自Invoke-Command
博士
The command uses the
Using
scope modifier to identify a local variable in a remote command. By default, all variables are assumed to be defined in the remote session. TheUsing
scope modifier was introduced in PowerShell 3.0.
- 由于你想要运行的辅助函数的名称存储在一个变量中,为了执行它,您需要使用 call operator
&
or the dot sourcing operator.
来调用它,即:& $choosen_function
. - 与其将
UserName
和Password
作为脚本的参数传递,我个人建议您在脚本中调用Get-Credential
。 -absolute_path
被用作run_commend_on_remote_server
的参数,但函数没有这样的参数。
理解了这些要点后,您可以通过以下方式处理脚本:
[cmdletbinding()]
param(
[ValidateSet('delete_directory', 'make_directory')]
$choosen_function,
$remote_address,
$absolute_path
)
function delete_directory{
# code here
}
function make_directory{
# code here
}
# store both function's definition, this will be used
# to pass them to the remote scope
$def = @(
${function:delete_directory}.ToString()
${function:make_directory}.ToString()
)
function run_commend_on_remote_server {
param ($choosen_function, $remote_address, $Credential, $absolute_path)
Invoke-Command -ScriptBlock {
# bring the definition of both functions to this scope
$deldir, $makedir = $using:def
# define both functions
${function:delete_directory} = $deldir
${function:make_directory} = $makedir
# invoke the chosen function
& $using:choosen_function -absolute_path $using:absolute_path
} -Credential $Credential -ComputerName $remote_address
}
# Here we call Get-Credential to get the pop-up for username and secure password
$cred = Get-Credential
$params = @{
choosen_function = $choosen_function
credential = $cred
remote_address = $remote_address
absolute_path = $absolute_path
}
run_commend_on_remote_server @params