Luis
Luis

Reputation: 3033

Run method async

I'm trying to run some of my custom code asynchronously in Powershell. The following tries to check for updates in a background thread:

Function CheckUpdates($manager)
{
    . "$PSScriptRoot\..\commands\upgradecmd.ps1";

    $upgradeCmd = New-Object UpgradeCmd -ArgumentList $manager;
    [bool]$upgradesAvailable = $false;

    try
    {
        $Global:silentmode = $true;

        $upgradeCmd.preview = $true;

        Start-Job -ArgumentList $upgradeCmd -ScriptBlock { param($upgradeCmd) $upgradeCmd.Run(); };

        Get-Job | Receive-Job;

        $upgradesAvailable = $upgradeCmd.upgradesAvailable;
    }
    finally
    {
        $Global:silentmode = $false;
    }

    if ($upgradesAvailable)
    {
        WriteWarning "Upgrades detected.";
        WriteWarning "Please, run the upgrade command to update your Everbot installation.";
    }
}

The problem is that inside the job (in the ScriptBlock), PS doesn't recognize anything about my custom "Run()" method, so it doesn't know how to call it. I've tried to "include" the class in the job using the -InitializationScript parameter with little success.

After searching the web, it seems that the way to do this is using PS Jobs, there's no thread handling in PS or something like "async". The point is that I just want to run a method of some class of my PS code asynchronously.

Upvotes: 0

Views: 80

Answers (1)

Sid
Sid

Reputation: 2676

Why don't you dot source inside the scriptblock?

Function CheckUpdates($manager)
{
    try
    {
        $Global:silentmode = $true

        $Scriptblock = {
            param($manager)
            . "<absolutepath>\upgradecmd.ps1"; #better to replace this with absolute path
            $upgradeCmd = New-Object UpgradeCmd -ArgumentList $manager;
            [bool]$upgradesAvailable = $false
            $upgradeCmd.preview = $true
            $upgradeCmd.Run()
            $upgradesAvailable = $upgradeCmd.upgradesAvailable;

            Return $upgradesAvailable
        }
        Start-Job -ArgumentList $manager -ScriptBlock $Scriptblock
        $upgradesAvailable = @(Get-Job | Wait-Job | Receive-Job) #This will probably not be so cut and dry but you can modify your code based on the return value
    }
    finally
    {
        $Global:silentmode = $false;
    }

    if ($upgradesAvailable)
    {
        WriteWarning "Upgrades detected.";
        WriteWarning "Please, run the upgrade command to update your Everbot installation.";
    }
}

I have added a Wait-Job as well before receiving it so your script would wait for the jobs to finish.

Upvotes: 1

Related Questions