Как показать шкалу прогресса с процентами внутри таблицы с использованием powershell

powershell progress bar

Practical Examples of Write-Progress in PowerShell

Let’s take a look at some examples of how to use Write-Progress in PowerShell:

Example 1: Copy Files with Progress Bar

In this example, we are using Write-Progress to display the progress of a script that is copying files from one location to another.

$Files = Get-ChildItem -Path "C:\Source"
$Destination = "C:\Destination"

$TotalFiles = $Files.Count
$Count = 0

Write-Progress -Activity "Copying Files" -Status "Starting" -PercentComplete 0

foreach ($File in $Files) {
    $Count++
    $PercentComplete = (($Count / $TotalFiles) * 100)
    $Status = "Copying $($File.Name)"

    Write-Progress -Activity "Copying Files" -Status $Status -PercentComplete $PercentComplete

    Copy-Item $File.FullName $Destination -Force
}

Write-Progress -Activity "Copying Files" -Status "Complete" -PercentComplete 100

Example 2: Download Files with Progress Bar

In this example, we are using Write-Progress to display the progress of a script that downloads files from the internet.

$Urls = @(
    "https://www.microsoft.com/downloads/SharePointSP1.msi",
    "https://www.microsoft.com/downloads/SharePointSP2.msi",
    "https://www.microsoft.com/downloads/SharePointSP3.msi"
)

# Destination folder
$destinationFolder = "C:\Downloads"

# Ensure the destination folder exists
if (-not (Test-Path $destinationFolder)) {
    New-Item -Path $destinationFolder -ItemType Directory
}

# Download each file
$totalUrls = $urls.Count
for ($i=0; $i -lt $totalUrls; $i++) {
    $url = $urls[$i]
    $fileName = [System.IO.Path]::GetFileName($url)  # Extract file name from URL
    $destinationPath = Join-Path -Path $destinationFolder -ChildPath $fileName

    # Display main progress
    Write-Progress -Activity "Downloading files" -Status ("Downloading " + $fileName) -PercentComplete (($i / $totalUrls) * 100)

    # Download file with sub-progress bar for individual file download
    Invoke-WebRequest -Uri $url -OutFile $destinationPath -Verbose
}

Write-Progress -Activity "Downloading files" -Completed -Status "All files downloaded!"
Write-Host "All files downloaded successfully!" -ForegroundColor Green

Understanding the Write-Progress cmdlet in PowerShell

Write-Progress is a cmdlet in PowerShell that allows you to display a progress bar in the console. It has several parameters that allow you to customize the appearance of the progress bar, including the percentage complete, the status message, and the activity name. Here are the parameters that you can use with Write-Progress:

Basic Write-Progress syntax looks like:

Write-Progress 
[-Activity] <String> 
[[-Status] <String>] 
[-PercentComplete <Int32>] 
[-SecondsRemaining <Int32>] 
[-Id <Int32>] 
[-ParentId <Int32>] 
[-Completed] 
[-SourceId <Int32>] 
[-CurrentOperation <String>] 
[<CommonParameters>]

Here are the important parameters of the Write-Progress cmdlet:

ParameterDescription
ActivityThe Activity parameter Specifies the title of the progress bar. This will appear as the first line of text.
StatusThis helps to display the current state of the activity or status of a running command in the status bar of the progress bar
PercentComplete0 to 100 percent done
SecondsRemainingCountdown timer
IdUnique ID to update specific bar
ParentIdGroup child progress bars

Write-Progres Example

  1. Use the Write-Progress cmdlet to create a new progress bar.
  2. Specify the parameters, such as -Activity, -Status, -PercentComplete, -SecondsRemaining, and -CurrentOperation to customize the progress bar.
  3. Update the progress bar periodically using the Write-Progress cmdlet with updated values for -PercentComplete.
  4. When the task is complete, use the Complete parameter to finish the progress bar.

To continually update the progress bar, we must place Write-Progress calls at certain points within your script’s logic, incrementing the PercentComplete each time. Here’s an example of a PowerShell script that uses the Write-Progress cmdlet to display a progress bar:

$Collection = 1..100
ForEach ($Item in $Collection) {
    Write-Progress -PercentComplete ($Item/100*100) -Status "Processing Items" -Activity "Item $item of 100"
    # Your actual script logic here
    Start-Sleep -Milliseconds 50
}
write-progress Powershell

And here is what it looks like in PowerShell ISE:

progress bar powershell

Using Write-Progress in PowerShell is relatively straightforward. Here’s a step-by-step guide on how to use it:

Step 1: Define the variables

The first step is to define the variable or collection that you will be using in your script. These variables will have the collection of data set you’ll be processing.

:/>  Как узнать модель материнской платы – 4 способа

Step 2: Start the progress bar and Perform Operation

The next step is to start the progress bar using the Write-Progress cmdlet and perform your target operation. You will need to specify the activity name and the status message.

Step 3: Update the progress bar

A common way to use Write-Progress is within a For loop in your script.

For($i=1; $i -le 100; $i++){

  Write-Progress -Activity "Processing Files" -Status "$i% Complete" -PercentComplete $i
  
  # Perform loop action
  sleep -Milliseconds 100  
}

This will iterate from 1 to 100, updating the progress bar each time with the current percent complete. You can update the status message to provide more context on which loop iteration is running.

Step 4: Complete the progress bar

Once your script has finished running, you have to complete the progress bar using the Write-Progress cmdlet. This will ensure that the progress bar is removed from the console.

Best practices for using progress bars in PowerShell

  • Only use a progress bar when necessary: While progress bars can be helpful, they can also slow down your script if overused. Only use a progress bar when necessary. If a task finishes instantly or in a very short time frame, showing a progress bar might be unnecessary and even counterproductive, as it could flash on and off too quickly for the user to see.
  • Update the progress bar frequently: Update the progress bar frequently to provide real-time feedback to the user. This will ensure that the user knows that the script is running and making progress.
  • Use clear and concise status messages: Use the -Activity and -Status parameters to provide clear and concise information about what’s happening. Use the -CurrentOperation parameter to offer additional context, especially if it helps users understand the current task.
  • Calculate Percentages Correctly: Ensure that your -PercentComplete value is accurately calculated. It should range from 0 to 100, representing the completion percentage.
  • Use Nested Progress Bars for Multi-Level Tasks: If your script has tasks within tasks (like copying multiple folders where each folder has multiple files), use parent-child progress bars. Use the -Id and -ParentId parameters to manage and display nested progress bars correctly.
  • Complete the Progress Bar: Use the -Completed switch to signal the end of the task, ensuring that the progress bar disappears or indicates completion. Also, Show progress at 0% before the operation starts.
  • Test your script with large data sets: Test your script with large data sets to ensure that the progress bar is working properly and that it doesn’t slow down your script.

Troubleshooting common issues with progress bars in PowerShell

While using a progress bar in PowerShell is relatively straightforward, there are a few common issues that you may encounter. Here are a few tips for troubleshooting these issues:

1. The progress bar not updating

If the progress bar is not updating, ensure you update it frequently enough. Check your -PercentComplete calculation. Ensure that it’s updating as expected within the loop or process. For loops that process items quickly, consider adding a small delay with Start-Sleep for visual clarity.

:/>  Как установить dll файл? » Полезные компьютерные программы и советы

If you are updating it frequently, and it still isn’t working, try running your script in a new PowerShell window.

2. Progress bar not displaying

If the progress bar is not displaying, ensure you start it with the Write-Progress cmdlet. If you are starting it with the Write-Progress cmdlet and it still isn’t working, ensure your loop or process is not finishing too quickly. The progress bar may not appear for very fast tasks.

3. Progress bar slowing down your script

4. Error: “Write-Progress : Cannot validate argument on parameter ‘PercentComplete’.

“The 110 is greater than the maximum allowed range of 100.”

Write-progress cannot validate argument on parameter percentcomplete. The 110 argument is greater than the maximum allowed range of 100
  • Cause: The value for ‘PercentComplete’ parameter exceeds the maximum limit of 100.
  • Solution: Ensure the ‘PercentComplete’ parameter is within the range of 0 to 100.

Here is the Official Microsoft Documentation reference for Write-Progress cmdlet!

Progress Bar GUI in PowerShell

For GUI-based progress bars, the Windows.Forms.ProgressBar .NET control can be used.

Here is a sample script:

Add-Type -AssemblyName System.Windows.Forms

$progressForm = New-Object System.Windows.Forms.Form
$progressForm.Width = 300
$progressForm.Height = 150
$progressForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
$progressForm.Text = "Processing data..."

$progressBar = New-Object System.Windows.Forms.ProgressBar
$progressBar.Location = New-Object System.Drawing.Point(10, 50)
$progressBar.Size = New-Object System.Drawing.Size(280, 20)
$progressForm.Controls.Add($progressBar)

$progressLabel = New-Object System.Windows.Forms.Label
$progressLabel.Location = New-Object System.Drawing.Point(10, 20)
$progressLabel.Size = New-Object System.Drawing.Size(280, 20)
$progressLabel.Text = "0% Complete"
$progressLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$progressForm.Controls.Add($progressLabel)

$progressForm.Show()

$data = 1..100
$index = 1
# Loop through the data and update the progress bar
foreach ($item in $data) {
    # Perform some operation on $item

    # Update the progress bar
    $progressPercent = ($index / $data.Count) * 100
    $progressBar.Value = $progressPercent
    $progressLabel.Text = "$progressPercent% Complete"
    Start-Sleep -Milliseconds 100
    $index++
}

$progressForm.Close()

This creates a configurable progress bar by setting properties like minimum, maximum, and step values. The control can then be updated by incrementing $ProgressBar.Value in your script.

powershell progressbar gui

Using Progress Bar with Multiple Operations

For extensive scripts involving multiple operations, you can segment the progress bar:

Write-Progress -Activity "Main Task" -Status "Task 1 of 3" -PercentComplete 33
# Task 1 logic
Start-Sleep -Seconds 1

Write-Progress -Activity "Main Task" -Status "Task 2 of 3" -PercentComplete 66
# Task 2 logic
Start-Sleep -Seconds 1

Write-Progress -Activity "Main Task" -Status "Task 3 of 3" -PercentComplete 100
# Task 3 logic
Start-Sleep -Seconds 1
write-progress example

Progress Bar with Countdown Timer

To show a countdown timer in the progress bar, use the SecondsRemaining parameter:

Write-Progress -Activity "Installing" -Status "Time Remaining" -SecondsRemaining $timeLeft

As $timeLeft decreases, the progress bar will visually count down the estimated time left. Here is a real-time example:

$progressParams = @{
    Activity = "Processing data"
    Status = "In progress"
    PercentComplete = 0
    SecondsRemaining = 60
    CurrentOperation = "Initializing"
}

Write-Progress @progressParams

$data = 1..10000
$index = 1
# Start the countdown timer
$timer = [Diagnostics.Stopwatch]::StartNew()

# Loop through the data and update the progress bar
foreach ($item in $data) {
    # Perform some operation on $item

    # Update the progress bar
    $progressParams.PercentComplete = ($index / $data.Count) * 100
    $progressParams.CurrentOperation = "Processing item $index of $($data.Count)"
    $progressParams.SecondsRemaining = (($timer.Elapsed.TotalSeconds / $index) * ($data.Count - $index)).ToString("F0")
    Write-Progress @progressParams

    $index++
}

# Complete the progress bar
Write-Progress -Completed -Activity "Completed"

Here is what it looks like in PowerShell ISE:

powershell progress bar count down timer

Here are a few more examples of Count down timers using the PowerShell Write-Progress cmdlet:

Function Start-Countdown {
    param (
        [Parameter(Mandatory=$true)]
        [int]$Seconds
    )

    # Countdown start time
    $StartTime = Get-Date
    $ElapsedTime =0

    # While there are still seconds left
    While ($ElapsedTime -lt $seconds) {
        # Calculate elapsed time
        $ElapsedTime = [math]::Round(((Get-Date) - $StartTime).TotalSeconds,0)
        
        # Update the progress bar
        Write-Progress -Activity "Counting down..." -Status ("Time left: " + ($Seconds - $ElapsedTime) + " seconds") -PercentComplete (($elapsedTime / $Seconds) * 100)
        #$Seconds = $Seconds - $elapsedTime

        # Wait for a second
        Start-Sleep -Seconds 1
    }

    # Once countdown is complete, close the progress bar
    Write-Progress -Activity "Counting down..." -Completed 
}

# Call the function to start a 10-second countdown
Start-Countdown -Seconds 10

Here is another example of how to show the Progress Bar in While Loop:

# Set total time for countdown timer
$timeRemaining = 20

while($timeRemaining -gt 0){

  # Calculate percentage
  $percentComplete = (($timeRemaining / 60) * 100)

  # Update progress bar
  Write-Progress -Activity "Deployment in progress" -Status "Time remaining: $timeRemaining seconds" -PercentComplete $percentComplete -SecondsRemaining $timeRemaining

  # Decrement timer
  $timeRemaining--

  # Wait 1 second
  Start-Sleep -Seconds 1
}

Nested (Parent-Child) Progress Bars for multi-level Operations

Parent-child progress bars are especially useful when you have a multi-level process. Here’s an example of a parent-child progress bar using Write-Progress. Let’s consider you’re processing multiple files, and for each file, you have several tasks to complete:

# Parent loop - processing files
1..5 | ForEach-Object {
    $fileNumber = $_

    # Parent progress
    Write-Progress -Activity "Processing Files" -Status "File $fileNumber of 5" -PercentComplete (($fileNumber / 5) * 100) -id 0

    # Simulate some file-specific tasks in a child loop
    1..10 | ForEach-Object {
        $taskNumber = $_

        # Child progress (nested within the parent)
        Write-Progress -Activity "Performing Task on File $fileNumber" -Status "Task $taskNumber of 10" -PercentComplete (($taskNumber / 10) * 100) -ParentId 0

        # Simulating time taken for each task with sleep
        Start-Sleep -Milliseconds 100
    }
}

# Completing the parent progress bar
Write-Progress -Activity "Processing Files" -Completed -Status "All files processed!"

The -ParentId parameter in Write-Progress for the child progress bar tells PowerShell that this progress bar is a child of another progress bar. The ID 0 typically refers to the most recent parent Write-Progress bar. Output:

:/>  Как восстановить Корзину на рабочем столе
Powershell write-progess Parent child progress bars

When you run the above script, you’ll see a top-level progress bar for file processing and a nested progress bar for tasks on each file.

Benefits of using a progress bar in PowerShell

1. Real-time Visual feedback

2. Time estimation to Track progress

A progress bar can also provide an estimate of how long your script will take to complete. This estimate can be incredibly helpful, especially when running scripts that take a long time to complete. It allows you to plan your time accordingly and ensures that you don’t waste time waiting for your script to finish.

3. Improved user experience

Using progress bars in PowerShell ForEach loops

Using a progress bar in a foreach loop can be incredibly helpful, especially when iterating over a large number of items. Here’s an example of how to use a progress bar in a foreach loop:

$Items = 1..10000

Write-Progress -Activity "Processing Items" -Status "Starting" -PercentComplete 0

foreach ($Item in $Items) {
    $PercentComplete = (($Item / $Items.Count) * 100)
    $Status = "Processing Item $($Item)"

    Write-Progress -Activity "Processing Items" -Status $Status -PercentComplete $PercentComplete

    # Do some processing
}

Write-Progress -Activity "Processing Items" -Status "Complete" -PercentComplete 100

Conclusion and final thoughts

What is a PowerShell progress bar?

Why would I use a Progress Bar in PowerShell?

How can I add a progress bar to my PowerShell script?

Is it possible to display multiple progress bars at once?

PowerShell supports nested progress bars, allowing you to display a parent progress bar and one or more child progress bars simultaneously.

How do I update the progress bar during a loop?

Inside a loop, you can update the progress bar by calling Write-Progress with updated values for -PercentComplete and other parameters at each iteration.

How do I remove the progress bar once the operation is complete?

The progress bar will automatically disappear once the script is completed. You can also manually remove it by calling Write-Progress with the -Completed parameter. For example: Write-Progress -Activity "Processing" -Status "Completed" -Completed

Оставьте комментарий