在 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

为了使该脚本正常工作,需要更改一些内容。

  1. 在您的 run_commend_on_remote_server 函数中,您使用的是用于交互式会话的 Enter-PSSession,然后您使用的是 Invoke-Command,在这种情况下,如果我理解您的意图正确 Enter-PSSession 必须删除
  2. 在同一函数中,在 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.

  1. 由于你想要运行的辅助函数的名称存储在一个变量中,为了执行它,您需要使用 call operator & or the dot sourcing operator . 来调用它,即:& $choosen_function.
  2. 与其将 UserNamePassword 作为脚本的参数传递,我个人建议您在脚本中调用 Get-Credential
  3. -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