Home > Software design >  Passing a Scriptblock with complex Arguments to a New Powershell Instance
Passing a Scriptblock with complex Arguments to a New Powershell Instance

Time:07-06

I want to execute the following script with complex arguments. For example with [securestring].

$text = "'This is a test message.'"

$ArgumentList = @( $text, $PID ) -join ", "
$cmd = { param([string]$msg, [int]$proc ); Write-Host "$msg FROM PID: $proc" }
$Command = "Invoke-Command -ScriptBlock {$cmd} -ArgumentList $ArgumentList"

Start-Process -Filepath powershell -ArgumentList "-noexit -command ( $Command )"

this script worked fine.
i`m transform this script into the new one

$text = "'This is a test message.'"
$Cred = get-credential
$ArgumentList = @( $text, $PID, $credential ) -join ", "
$cmd = { param([string]$msg, [int]$proc, $Credential ); Write-Host "$msg FROM PID: $proc, cred: $( $Credential.username )" }
$Command = "Invoke-Command -ScriptBlock {$cmd} -ArgumentList $ArgumentList"

Start-Process -Filepath powershell -ArgumentList "-noexit -command ( $Command )"

I have an error. How to pass arguments right?

CodePudding user response:

As suggested by @Mathias, I would consider to run the whole process under the specific credentials

Start-Process -Credential $cred -Filepath powershell -ArgumentList "-noexit -command ( $Command )"

Anyways, you might also serialize (all) your arguments and convert it to Base64 as you passing it trough multiple interpreters:

$text = "This is a test message."
$Cred = get-credential
$Arguments = @{
    Msg  = $Text
    Proc = $PID
    Cred = $Cred
}
$Serialized = [System.Management.Automation.PSSerializer]::Serialize($Arguments)
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($Serialized)
$Base64 =[Convert]::ToBase64String($Bytes)
$cmd = {
    param([String]$Base64)
    $Serialized = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Base64))
    $Arguments = [System.Management.Automation.PSSerializer]::Deserialize($Serialized)
    Write-Host " $($Arguments.msg) FROM PID: $($Arguments.proc), cred: $( $Arguments.Cred.Username)"
}
$Command = "Invoke-Command -ScriptBlock {$cmd} -ArgumentList $Base64"

Start-Process -Filepath powershell -ArgumentList "-noexit -command ( $Command )"

Note: that Get-Credential by default uses the Windows data protection API, and the key used to encrypt the password is specific to both the user and the machine that the code is running under.

  • Related