I have a function that I should be able to call from any place in my powershell script.
The problem is that it doesn't identify the function in a script block.
In the following example I have the function getNumberFive
which should return the number 5.
I want to be able to use this function inside a scriptblock when I start a new job and also in the end of the script.
Expected result:
Write the number 15 to the file "C:\tmp\result.txt"
Write to the console: "I like the number 5"
In reality:
Write the number 10 to the file "C:\tmp\result.txt"
Write to the console: "I like the number 5"
I can workaround this issue by defining the same function inside the scriptblock but then I will duplicate the function and this is not a good programming.
Another way is to define:
$func = {
function getNumberFive(){
return 5
}
}
$scriptBlock = {
Function printSum(){
$number = getNumberFive
$newNumber = 10 + $number # => $newNumber should be 15
$newNumber >> "C:\tmp\result.txt"
}
}
Start-Job -ScriptBlock $scriptBlock -InitializationScript $func
But in this case I won't be able to call $five = getNumberFive
.
I read number of methods but I didn't understand how exactly to use them:
CALLING A POWERSHELL FUNCTION IN A START-JOB SCRIPT BLOCK WHEN IT’S DEFINED IN THE SAME SCRIPT
How to pass a named function as a parameter (scriptblock)
PowerShell: Pass function as a parameter
Using Invoke-Command -ScriptBlock on a function with arguments
My script:
function getNumberFive(){
return 5
}
$scriptBlock = {
Function printSum(){
# $number = getNumberFive => DOESN'T WORK
# $number = Invoke-Expression ($(get-command getNumberFive) | Select -ExpandProperty Definition) => DOESN'T WORK AS EXPECTED
# $number = &(${function:getNumberFive}) => DOESN'T WORK AS EXPECTED
# $number = &(Get-Item function:getNumberFive) => DOESN'T WORK AS EXPECTED
$newNumber = 10 + $number # => $newNumber should be 15
$newNumber >> "C:\tmp\result.txt"
}
printSum
}
Start-Job -ScriptBlock $scriptBlock
$five = getNumberFive
Write-Host "I like the number"$five
Get-Job | Wait-Job
Get-Job | Stop-Job
Get-Job | Remove-Job
When you pass a scriptblock to
start-job
(orinvoke-expression
) the PowerShell instance that executes that scriptblock only has access to that scriptblock, anything that script block loads, and anything that already exists in the PowerShell instance.Other parts of your script are not included. (For functions locally defined in your script to be available from other, possibly remote, instances of PowerShell the whole script – not just the scriptblock – and any dependencies would need to be accessible from the other instance.)
You could refactor the code you want in both places into a module which the script block loads as well as the job creating script.
When using jobs you are executing code in another process: like any remote operation the remote executing is a separate environment.