Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write-progress during Start-process -Wait

Tags:

powershell

I'm trying to create an installation script and display a progress bar during the install.

$localfolder= (Get-Location).path
start-process -FilePath "$localfolder\Installer.exe" -ArgumentList "/silent /accepteula" -Wait

and as progress bar I want to add:

for($i = 0; $i -le 100; $i++)
{
Write-Progress -Activity "Installer" -PercentComplete $i -Status "Installing";
Sleep -Milliseconds 100;
}    

But I can't find the way to run the progress bar while the installer is running.

If someone has an idea...

like image 458
Chris Avatar asked Mar 06 '23 15:03

Chris


1 Answers

You could muck around with threading options, for your progress bar, but I don't recommend it.

Instead, forego -Wait with Start-Process, and use -PassThru to return a [System.Diagnostics.Process] object.

With that, you can check for the process having terminated yourself.

This is important for two reasons, both related to the fact that your progress bar isn't actually tracking the progress of the installation:

  1. You want to be able to abort the progress bar as soon as the process is finished.
  2. You maybe want to reset the progress bar to 0 if it happens to take longer than 10,000 milliseconds.

The Process object has a boolean property called .HasExited which you can use for this purpose.

With all that in mind, I'd do something like this:

$localfolder= (Get-Location).path
$process = Start-Process -FilePath "$localfolder\Installer.exe" -ArgumentList "/silent /accepteula" -PassThru

for($i = 0; $i -le 100; $i = ($i + 1) % 100)
{
    Write-Progress -Activity "Installer" -PercentComplete $i -Status "Installing"
    Start-Sleep -Milliseconds 100
    if ($process.HasExited) {
        Write-Progress -Activity "Installer" -Completed
        break
    }
}

Summary of Changes

  • Start-Process now uses -PassThru instead of -Wait and assigns the process object to the $process variable.
  • The for loop's iterator uses $i = ($i + 1) % 100 instead of $i++, so that it keeps resetting to 0 when it reaches 100.
  • An if block checks to see if the process has exited; if so, it ends the progress bar and then breaks out of the loop.

Slight caveat: the for loop is now an infinite loop that only breaks when the process exits. If the process is stuck, so is the loop. You could separately time the operation and handle a timeout if you wanted to.

like image 195
briantist Avatar answered Mar 16 '23 16:03

briantist