简体   繁体   中英

How do I write to the console from inside start-job with BeginInvoke in Powershell?

I'm pretty new to Powershell and I'm trying to write a script to run some parallel jobs. I'd like those jobs to output some data when they're done running, but I can't seem to get it right. I've messed with it a bit and it sounds like Write-Output is the way to go but when I look at the objects returned by the job there isn't anything in the output array. This is what I have so far:

$connection = @{ connection = (Connect-Site -Url "site.com" -Browser) }

$importScript = {

        param($p1)

        #get the list name from the file name
        $name = $_.Name.LastIndexOf(".")
        $path = $_.FullName
        $listName = $_.Name.Substring(0, $name)

    $dstSite = Connect-Site -Url "site.com" -UseCredentialsFrom $p1.connection

        Write-Output "$name, $path, $listName"

        Write-Output $dstSite
}

Write-Host "Migration started at $(Get-Date)" 

Get-ChildItem -Path "C:\ProjExports" | 
Foreach-Object {

    $running = @(Get-Job | Where-Object { $_.State -eq 'Running' })


        if ($running.Count -le 10) {
            Start-Job {

                # create and start the job
                $p = [PowerShell]::Create()
                $null = $p.AddScript($importScript).AddArgument($connection)
                $job = $p.BeginInvoke()

                $done = $job.AsyncWaitHandle.WaitOne()

                $out = $p.EndInvoke($job)

            }
        } else {
             $running | Wait-Job
        }
        Get-Job | Receive-Job

}

I'm under the impression that $out should contain the items from Write-Output of the script in AddScript but it always seems to be empty.

You're combining runspaces and jobs, and it's not necessary. A job can be as simple as this. A job creates a new process, so there's somewhat of a delay.

'hi','you','me' | foreach-object { 
  start-job { param ($a) write-output "$a there" } -args $_ 
} | receive-job -wait -autoremovejob

you there
me there
hi there

If you have powershell 7, you can use start-threadjob or foreach-object -parallel instead. Or download the Threadjobs module in powershell 5.

Here's a real world threadjob example:

echo microsoft.com yahoo.com | foreach { 
  start-threadjob { 
    param ($hostname) 
    test-connection -count 1 $hostname } -argumentlist $_ 
} | receive-job -wait -autoremovejob

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM