Search code examples
.netpowershellpaintstatusbar

Creating and updating a status panel


I'm trying to make a GUI in powershell using some .net and given my small amount of experience writing GUI based programs I'm running into trouble updating a label.

I'm just making a simple form that has a label, and I want the label to be replaced each time a folder name is read. The idea is to mimic a status window for a program that takes some time to run and updates a panel with information on the progress of the program.

Here is my code:

$form = New-Object System.Windows.Forms.Form
$form.Height = 350
$form.Width = 600

$label = New-Object System.Windows.Forms.Label
$label.Text = "first label"
$form.Controls.Add($label)
$form.showDialog()

$dir = ls C:\ -Directory
[int]$i = 0

while($i -lt $dir.Count) {

   $label.Text = $dir[$i].Name
   $form.Controls.Add($label)
   $form.paint
   sleep 3 # Added this just to make sure I'm not missing the display
   $i++
}

I assume there needs to be a call to paint, but I'm not sure how that would update the GUI.


Solution

  • Here is an answer to your question. I replace $form.ShowDialog() by $form.Show(). I also add the $form.Close() at the end but the result is not so good for me ; look at the end for a more PowerShell solution.

    [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    $form = New-Object System.Windows.Forms.Form
    $form.Height = 350
    $form.Width = 600
    
    $label = New-Object System.Windows.Forms.Label
    $label.Text = "first label"
    $form.Controls.Add($label)
    $form.Show()
    
    $dir = ls C:\ -Directory
    [int]$i = 0
    
    while($i -lt $dir.Count) {
    
       $label.Text = $dir[$i].Name
       $form.Controls.Add($label)
       #$form.paint
       sleep 1 # Added this just to make sure I'm not missing the display
       $i++
    }
    
    $form.Close()
    

    Coding advice : Consider using foreach loop in spite of a while loop here foreach ($file in $dir). No need here to type $i as an int. In scripts try to use CmdLet full name (Get-ChilItem), and not aliases (ls, dir ...), even if they are common aliases, it's more readable. Don't get upset, you can forget this ;o)

    Now my advice on the way you decide to handle your problem. PowerShell provides some stuff to show progress. Here is a small example :

    $dirs = Get-ChildItem C:\ -Directory
    $i = 0
    foreach($dir in $dirs)
    {
       Write-Progress -Activity "looking for Directories" -status "Found $($dir.fullname)" -percentComplete ($i*100 / $dirs.count)
       sleep 1 # Added this just to make sure I'm not missing the display
       $i++
    }