Vijay
Vijay

Reputation: 55

Powershell Passing Function to remote command

I am trying to pass local function to remote code but not getting any success. Below is my code.

#variables defined over here
...
function comparehash ($source, $destination)
{
    $sourcefiles = @{}
    ...
}

$securePassword = ConvertTo-SecureString -AsPlainText -Force $Password 
$cred = New-Object System.Management.Automation.PSCredential $Username, $securePassword
$session = New-PSSession -ComputerName $srv -port 22 -Credential $cred  –Authentication CredSSP
Invoke-Command -Session $session -ScriptBlock { 
    param( $source, $destination, $application)
    #Write-Host "This is" $source
    # Take backup of the site first
    Copy-Item $source\$application $destination -Recurse -force
    ${function:comparehash}
}  -ArgumentList $site_path_local, $backup_path, $app
Remove-PSSession -Session $session

This code is copying source files to destination. Function has been created to validate md5 sum of the copied files. When I run the script script runs fine but it doesn't call the function code. Is there anything additional need to be done to call function?


Update

Invoke-Command -Session $session -ScriptBlock { 
    param( $source, $destination, $application, $fundef, $comparefunc )
    Write-Host "This is" $source, $destination
    # Take backup of the site first
    #Copy-Item $source\$application $destination -Recurse -force
    [ScriptBlock]::($comparefunc).Invoke($source,$destination)
    #comparehash $site_path_local $backup_path
}  -ArgumentList $site_path_local, $backup_path, $app, ${function:comparehash}
Remove-PSSession -Session $session

Above code is throwing following error:

PS C:\Windows\system32> C:\Users\vijay.patel\Documents\myscripts\Env_Refresh.ps1
This is F:\inetpub F:\Env_Backup\Refresh_Backup\
You cannot call a method on a null-valued expression.
    + CategoryInfo          : InvalidOperation: (Invoke:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
    + PSComputerName        : 172.16.82.124

Upvotes: 3

Views: 4117

Answers (2)

Brain2000
Brain2000

Reputation: 4894

I found the $Using command can be your friend here. If you keep the remote PSSession open, you can transfer all the functions you will need one at a time, then invoke the final scriptblock that calls/uses those functions.

function comparehash($source, $destination)
{
    Write-Output "I like hash";
    if( $source -eq $destination) { PackThePipe $source; }
}

function PackThePipe($hash)
{
    Write-Output "Pushing $hash through the pipe";
}


$session = New-PSSession -ComputerName $srv -port 22 -Credential $cred  –Authentication CredSSP

#create the functions we need remotely
Invoke-Command $session { Invoke-Expression $Using:function:comparehash.Ast.Extent.Text; }
Invoke-Command $session { Invoke-Expression $Using:function:PackThePipe.Ast.Extent.Text; }

#call the scriptblock that utilizes those functions
Invoke-Command $session { $s = "12345"; $d="12345"; comparehash $s $d; }

Remove-PSSession $session;

Upvotes: 3

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174505

Since the function is defined in your own local scope, you'll have to pass it along to the remote session as well. Through testing, it seems that it gets passed as a string, but you can use [scriptblock]::Create() to "recreate" it in the remote session:

Invoke-Command -Session $session -ScriptBlock { 
    param( $source, $destination, $application, $comparefunc)
    # do stuff
    # Now invoke the function that was provided
    [ScriptBlock]::Create($comparefunc).Invoke($source,$destination)
} -ArgumentList $site_path_local, $backup_path, $app, ${function:comparehash}

Upvotes: 4

Related Questions