使用 Invoke-Command Powershell 命令的 -ScriptBlock 中的参数调用函数

发布于 2025-01-10 20:32:51 字数 1369 浏览 0 评论 0原文

我有两台服务器,其中一台是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

I have two server one of them is Active directory and other is Windows10.
I want to write a Powershell script that delete and make a directory.(for easy situation I choose delete and make directory but in real, The script used for getting group and organization unit of active directory.)

I write three function and below Powershell script. the first one is for run command on remote server and two of them for create and delete a directory. The 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

When I run this script as below I got errors:

my_powershell_script.ps1 -choosen_function make_directory -username admin -password admin -remote_address 192.168.2.22

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晚风撩人 2025-01-17 20:32:51

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

  1. 在您的 run_commend_on_remote_server 函数中,您使用的是用于交互式会话的 Enter-PSSession,然后您使用的是 Invoke-Command,在这种情况下,如果我正确理解您的意图,Enter-PSSession 必须删除
  2. 在同一函数上,在 Invoke-Command 脚本块内,正在使用 $choosen_function,但是尚未在该范围内定义 2 个辅助函数 (远程范围)。如果您想远程使用函数,则需要传递函数的定义。同样的情况也适用于 $absolute_path。为了将本地定义的变量传递到远程作用域,您可以使用 -ArgumentList$using:,请参阅 示例 9 来自 Invoke-Command 文档。

该命令使用 Using 范围修饰符来标识远程命令中的本地变量。默认情况下,假定所有变量都在远程会话中定义。 Using 范围修饰符是在 PowerShell 3.0 中引入的。

  1. 由于您要运行的辅助函数的名称存储在变量中,因此为了执行它,您需要使用调用运算符&点采购运算符 . 来调用它,即:& $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

There are a few things which need to be changed in order for this script to work.

  1. On your run_commend_on_remote_server function, you're using Enter-PSSession which is meant for interactive sessions, and then you're using Invoke-Command, in this case if I understand your intent correctly Enter-PSSession has to be removed.
  2. On the same function, inside Invoke-Command script blocks's, $choosen_function is being used however the 2 helper functions have not been defined on that scope (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 from the Invoke-Command Doc.

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. Since the name of the helper function you want to run is stored in a variable, in order to execute it, you would need to use the call operator & or the dot sourcing operator . to invoke it, i.e.: & $choosen_function.
  2. Instead of passing UserName and Password as argument of your script, I would personally recommend you to call Get-Credential inside your script.
  3. -absolute_path is being used as parameter for run_commend_on_remote_server but the function does not have such parameter.

With these points being understood, here is how you could approach your script:

[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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文