Start-Job with custom object

I am having an issue getting some code to work. I am creating a backup service that utilizes some custom objects. It is failing on the Start-Job line in the sense that it is not calling my custom BackupJob Start function. I’m assuming it’s a problem with context as I think Start-Job launches in a new context which would not know about BackupJob and thus would be unable to find the correct method to use. How can I use the current session’s context in subsequent jobs?

class Backup {
    [BackupJob[]]$BackupJob

    Backup([string] $configfile) {
         Get-Content $configfile | Where-Object { $_ -notmatch "^#.*" } | ForEach-Object { $this.BackupJob += [BackupJob]::new($_) }
    }

    [void]Start() {
        foreach ($job in $this.BackupJob) {
            # The next line is where it's failing. I'm assuming because the new Job context doesn't include 
            # information it needs to know about the Backup and BackupJob objects.
            Start-Job -Name $job.DisplayName -Scriptblock { $input.Start() } -InputObject $job
        }
    }
}

class BackupJob {
    [string]$MountPoint
    [string]$DisplayName
    [string]$OutputPath

    BackupJob([string] $configLine) {
        $splitline = $configLine.split(";")
        $this.MountPoint = $splitline[0]
        $this.DisplayName = $splitline[1]
        $this.OutputPath = $splitline[2]
    }

    [void]Start() {
        # Do work here
    }
}

Jon,
Welcome to the forum. :wave:t4:

I don’t know how it is with classes but I recently stumbled across a similar approach regarding functions … it might help you.

https://stackoverflow.com/a/71887657

So I did figure this out, but not sure if there might be a better way. This is what I came up with. Basically I’m importing this script into a variable $initscript and recreating the BackupJob object in the Start-Job context (the $script variable). Both of those variables are getting sent to Start-Process. Seems to work, but I wish there was a way to allow me to import the script as a scriptblock without having to remember to put semi-colons everywhere.

EDIT: I figured out the semicolon issue. When I load the backup script in to $initscript, I had to add -Raw so it preserved the newlines. Works perfectly now!

# Output of Backup.ps1
class Backup
{
    [BackupJob[]]$JobList;

    Backup([string] $configFileName)
    {
        Get-Content -Path $configFileName |
            Where-Object { $_ -notmatch "^#.*" } |
            ForEach-Object { $this.JobList += [BackupJob]::new($_) };
    }

    [void]Start()
    {
        foreach ($currentjob in $this.JobList) 
        {
            $initScript = [scriptblock]::Create("$(Get-Content ".\Backup.ps1")");
            $script = {
                $job = [BackupJob]::new($input.MountPoint, $input.DisplayName, $input.OutputPath, $input.ExclusionList);
                $job.Start();
            };
            Start-Job -Name $currentjob.DisplayName -ScriptBlock $script -InputObject $currentjob -InitializationScript $initScript;
        }
        while ((Get-Job | Where-Object State -eq Running).Count -gt 0)
        {
            Write-Host "$((Get-Job | Where-Object State -eq Running).Count) Jobs still working";
            Start-Sleep -Seconds 5;
        }
        $this.JobList | ForEach-Object { Write-Host (Get-Job -Name $_.DisplayName | Receive-Job); Get-Job -name $_.DisplayName | Remove-Job };
        Write-Host "All jobs complete";
    }
}

class BackupJob
{
    [string]$MountPoint;
    [string]$DisplayName;
    [string]$OutputPath;
    [string[]]$ExclusionList;

    BackupJob([string] $config) 
    {
        $splitconfig = $config.split(";");
        $this.MountPoint = $splitconfig[0];
        $this.DisplayName = "$($splitconfig[0].Substring(0,1))_DRIVE";
        $this.OutputPath = $splitconfig[1];
        $this.ExclusionList = $splitconfig[2];
    }

    BackupJob([string]$mp, [string]$dn, [string]$op, [string[]]$el) 
    {
        $this.MountPoint = $mp;
        $this.DisplayName = $dn;
        $this.OutputPath = $op;
        $this.ExclusionList = $el;
    }

    [void]Start()
    {
        # Do our work. This is just  dummy script
        $i = Get-Random -Minimum 10 -Maximum 60;
        Write-Host $i;
        Start-Sleep -Seconds $i;
    }
}