1

I'm ashamedly plagiarising part of an answer given by @mjolinor, here, It works until I replace copy-fileHC with $FunctionName. I need to be able to pass the name of the function to call as a variable.

I think I am getting caught out because the script block can't 'see' the $FunctionName variable, but I am unsure how to get it to work. I have tried passing a separate param($functionName) but still, it doesn't work.

Here is my script thus far (that works):

Function Invoke-FunctionRunAs
{
    [cmdletbinding()]
    Param
    (
        [string]$FunctionName,
        [HashTable]$FunctionParameters,
        [System.Management.Automation.CredentialAttribute()]$Credentials
    )

    $CallingUser = [Security.Principal.WindowsIdentity]::GetCurrent().Name

    $RunAsDomain = $credentials.GetNetworkCredential().Domain
    $RunAsUser = $Credentials.GetNetworkCredential().username

    if(-not($RunAsDomain))
    {
        $RunAsDomain = "."
    }

    #$functionParameters.Add('FunctionName', $FunctionName)    

    Write-Verbose "Calling user: $CallingUser"
    Write-Verbose "Attempting to run scriptblock as $RunAsDomain\$RunAsUser"
    Write-Verbose "Called function: $functionName"
    Write-Verbose ("Passed parameters: $($FunctionParameters | Out-String)") 
    #$FunctionName = "Function:$FunctionName"

    $ScriptBlock = [scriptblock]::Create(".{${Function:Test-Function}} $(&{$args}@FunctionParameters)") #https://stackoverflow.com/questions/28234509/powershell-splatting-the-argumentlist-on-invoke-command

    $ScriptBlock
    Invoke-Command -ComputerName . -Credential $credentials -ScriptBlock $ScriptBlock #-ArgumentList $FunctionName

}

And called thus:

$params = @{
    Contents = "'Some new text. 003'"
    Number = 3.54*10
}

$credential = New-Object System.Management.Automation.PSCredential('COMPUTER\SomeUser',(ConvertTo-SecureString 'SomeUserPassword' -AsPlainText -Force))

Invoke-FunctionRunAs -FunctionName "Test-Function" -FunctionParameters $params -Credentials $credential -Verbose

However, replacing function:Test-Function with function:$FunctionName doesn't work. It doesn't see the function at all. The output of $scriptblock looks like:

.{} -Number: 35.4 -Contents: 'Some new text. 003'

When it works the whole function is printed out inside the {}.

In a previous, similar, question of mine, @Daryl had a problem with a hypen in the functions name, so to test, I renamed Test-Function to TestFunction, but to no avail.

I'd be grateful for any suggestions / ideas.

(PS V 5.1 / Win 10)

1 Answer 1

1

The parser will recognize $functionName as the literal function name. Use Get-Content against the function: drive instead:

$functionDefinition = Get-Content function:\$functionName
$ScriptBlock = [scriptblock]::Create(".{${functionDefinition}} $(&{$args}@FunctionParameters)")

This also allows for some proper error handling in case the function name does not actually refer to an existing function:

try{
    $functionDefinition = Get-Content function:\$functionName -ErrorAction Stop
    $ScriptBlock = [scriptblock]::Create(".{${functionDefinition}} $(&{$args}@FunctionParameters)")
}
catch{
    throw New-Object Exception "Function $functionName was not found in the current execution context",$_
    return
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.