Search code examples
windowspowershellcmdparallel-processingstreaming

How do I run multiple instances of my Powershell function in parallel?


Below is my function present in file streamMonitor.ps1.

function streamMonitor {
    [cmdletbinding()]
    param(
      [string]$directoryPath,
      [string]$scriptToRestartPath
    )

    while ($true) {
        Write-Host "Monitoring directory: $directoryPath"
        Write-Host "Script to restart: $scriptToRestartPath"

        # Get the current time
        $currentTime = Get-Date

        # Get the latest creation time of any file in the directory
        $latestCreationTime = Get-ChildItem -Path $directoryPath -Recurse |
          Where-Object { !$_.PSIsContainer } |
            Sort-Object CreationTime -Descending |
              Select-Object -First 1 |
                ForEach-Object { $_.CreationTime }

        # Ensure $latestCreationTime is not $null
        if ($null -eq $latestCreationTime) {
            Write-Host "No files found in the directory."
            return
        }

        # Check if the latest write time is within the last 30 seconds
        $timeDifference = New-TimeSpan -Start $latestCreationTime -End $currentTime
        if ($timeDifference.TotalSeconds -gt 30) {

            # No changes in the last 30 seconds, restart the specified script
            Write-Host "No changes detected within the last 30 seconds. Restarting script..."
            Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$scriptToRestartPath`"" -NoNewWindow
        } else {
            Write-Host "Changes detected within the last 30 seconds. No action taken."
        }

        Start-Sleep -Seconds 30
        continue
    }
}

My streamMonitor function works fine, so I'm confused what the issue is.

A different file called invokingStream.ps1, where I would like to call multiple instances of the function.

What do I need to change in order to get these jobs to run in parallel?

When I run this file, nothing happens, it just completes the process. However with the function it is calling, it should run indefinitely.

I am running PS 5.1

#Invoking Functions in Parallel
$job1 = Start-Job -ScriptBlock { 
    . C:\pathto\streamMonitor.ps1
    streamMonitor -directoryPath "C:\pathto\stream1" -scriptToRestartPath "C:\pathto\stream1.bat"
}

$job2 = Start-Job -ScriptBlock { 
    . C:\pathto\streamMonitor.ps1
    streamMonitor -directoryPath "C:\pathto\stream2" -scriptToRestartPath "C:\pathto\stream2.bat"
}

$job3 = Start-Job -ScriptBlock { 
    . C:\pathto\streamMonitor.ps1
    streamMonitor -directoryPath "C:\pathto\stream3" -scriptToRestartPath "C:\pathto\stream3.bat"
}

Solution

  • Something you're missing in your code is blocking the thread that starts the jobs, otherwise, your script ends right after invoking them and in consequence the jobs also end. You can use Receive-Job -Wait for this, it also allows you to get back the Write-Host output to your main thread.

    $streamMonitor = @(
        @{
            directoryPath       = 'C:\pathto\stream2'
            scriptToRestartPath = 'C:\pathto\stream2.bat'
        }
        @{
            directoryPath       = 'C:\pathto\stream3'
            scriptToRestartPath = 'C:\pathto\stream3.bat'
        }
        @{
            directoryPath       = 'C:\pathto\stream1'
            scriptToRestartPath = 'C:\pathto\stream1.bat'
        }
    )
    
    $streamMonitor | ForEach-Object {
        Start-Job {
            . C:\pathto\streamMonitor.ps1
            streamMonitor @using:_
        }
    } | Receive-Job -Wait -AutoRemoveJob