简体   繁体   中英

Call function with arguments in -ScriptBlock of Invoke-Command Powershell command

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

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, ie: & $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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM