Another Start-Job example

In reference to the post I made yesterday about Start-Job, here is an example where the function is passed into the Start-Job so it can be reused inside of that child process. This enables you to A) make code that can be spawned to many child processes while only writing it once, and B) make it so a child process can continue re-using the code. You don’t need to define a function explicitly, you can just have some code in a variable that you use Invoke-Expression on when you need to run it. I personally prefer writing functions normally, and I am not sure of the memory implications when using Invoke-Expression multiple times aside from the pitfalls of scope. With functions you can at least have a separation of scope from the global child process, so you can keep your variables organized accordingly. I dropped in an example script that also shows how to pass credentials to ntfy.sh. If you run your own instance, it’s a good idea to lock it down so it doesn’t get abused by bots/people that would find it.

$computer = '1.1.1.1'
$uri = "https://ntfy.sh/<topic name>"
$credentials = 'username:yourpassword'
$global:encodedCredentials = [convert]::ToBase64String([text.Encoding]::UTF8.GetBytes($credentials))

$script = 'function test_func(){
ping $computer -n 1
        If ( $LASTEXITCODE -eq 0 ) {
        $headers = @{
        Authorization = "Basic $global:encodedCredentials"
        Title = "Unattend complete."
        Tags = "information_source"
        Priority = "3"
        }
        $message = "$computer is online."
        Invoke-RestMethod -Method ''Post'' -Uri $global:uri -Headers $headers -Body $message -UseBasicParsing
}
}
'


Start-Job -ArgumentList ($computer,$uri,$global:encodedCredentials,$script) -ScriptBlock {
param ($computer,$uri,$global:encodedCredentials,$script)
Invoke-Expression $script
test_func
}

While I’m mentioning scope, I made a quick example to demonstrate the point of scopes and why it matters.

$global:timer = 2700

function test($timer){
Write-Host "Global `$global:timer $global:timer"
Write-Host "Function `$timer $timer"
Write-Host "As you can see, it is defined by the global timer."
$timer=Read-Host -Prompt "Enter in a number"   # Defining the timer inside of the function.
Write-Host "Function `$timer $timer"
Write-Host "Variable has changed inside of the function."
Write-Host "Now I'm going to modify the `$global:timer."
$global:timer = $timer
}

test($timer)
Write-Host "Global `$timer $timer"
Write-Host "As you can see, it has changed based on the variable from the function."

When you run the above code, the final number in the $global:timer variable is whatever is entered while running the function. You can define a variable outside of the function with a default value, but once in the function have it set it’s own definition and thusly change the behavior. I would write another example but this post is lengthy enough as is. More later.

Leave a Reply

Your email address will not be published. Required fields are marked *