How to update GUI when running a function, or a series of functions

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
flho_fvr
Posts: 6
Meble kuchenne na zamówienie - na wymiar - Wrocław
Joined: Mon Feb 03, 2020 12:22 am

How to update GUI when running a function, or a series of functions

Post by flho_fvr »

Hi
Trying to get a gui to display a message "configurering... please wait, and then call the function, and at the end update with a final "all processed" wait 3 seconds and close the gui.
  1. Function updateConfig
  2.  
  3. {
  4.  
  5.     <doing some stuff>
  6.  
  7.     $endDate = Get-Date
  8.  
  9.     $statusMessage = "All processed ($endDate), please wait...!"
  10.  
  11.     $richtextbox1.Text = $statusMessage
  12.  
  13.     $richtextbox1.Update()
  14.  
  15.     Start-Sleep -Seconds 3
  16.  
  17.     $formUpdateConfiguration.Close()
  18.  
  19. }
  20.  
  21.  
  22.  
  23. $formUpdateConfiguration_Load = {
  24.  
  25.     $date = Get-Date
  26.  
  27.     $statusMessage = "Configuring ($date), please wait..."
  28.  
  29.     $richtextbox1.Text = $statusMessage
  30.  
  31.     $richtextbox1.Update()
  32.  
  33.     updateConfig
  34.  
  35. }
The reason for autoclose is that I have 3 functions to execute, and another, and maybe better, approach would be displaying a GUI, run the 3 functions and update the GUI for every function.

Any ideas?

Best regards
/Flemming

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: How to update GUI when running a function, or a series of functions

Post by jvierra »

You will have to force an update after you change a control. This is usually done by executing the following line:
[System.Windows.Forms.Application]::DoEvents()

The thing to keep in mind id that a GUI executes all code in an event. As long as the code in teh event is executing the GUI will remain frozen. "DoEvents" allows the form to process messages and update controls.

flho_fvr
Posts: 6
Joined: Mon Feb 03, 2020 12:22 am

Re: How to update GUI when running a function, or a series of functions

Post by flho_fvr »

Hi jvierra

Thanks for you help - I do appreciate it.

It seem's I'm still doing it wrong... tried to do the following, but it seem's Im not using your suggestion correctly - can you help me out?
  1. function loadOne
  2.  
  3. {
  4.  
  5.     [System.Windows.Forms.Application]::DoEvents()
  6.  
  7.     $Script:oneDate = Get-Date
  8.  
  9.     $statusMessage = "$([char]0x2022) Configuring partOne ($oneDate), please wait..."
  10.  
  11.     $richtextbox1.Text = $statusMessage
  12.  
  13.     Write-Host "One"
  14.  
  15.     Start-Sleep -Seconds 3
  16.  
  17. }
  18.  
  19.  
  20.  
  21. function loadTwo
  22.  
  23. {
  24.  
  25.     [System.Windows.Forms.Application]::DoEvents()
  26.  
  27.     $Script:twoDate = Get-Date
  28.  
  29.     $statusMessage = "$([char]0x2022) Configuring partOne ($oneDate), please wait...`n$([char]0x2022) Configuring partTwo ($twoDate), please wait..."
  30.  
  31.     $richtextbox1.Text = $statusMessage
  32.  
  33.     Write-Host "Two"
  34.  
  35.     Start-Sleep -Seconds 3
  36.  
  37. }
  38.  
  39.  
  40.  
  41. function loadThree
  42.  
  43. {
  44.  
  45.     [System.Windows.Forms.Application]::DoEvents()
  46.  
  47.     $Script:threeDate = Get-Date
  48.  
  49.     $statusMessage = "$([char]0x2022) Configuring partOne ($oneDate), please wait...`n$([char]0x2022) Configuring partTwo ($twoDate), please wait...`n$([char]0x2022) Configuring partThree ($threeDate), please wait..."
  50.  
  51.     $richtextbox1.Text = $statusMessage
  52.  
  53.     Write-Host "Three"
  54.  
  55.     Start-Sleep -Seconds 3
  56.  
  57. }
  58.  
  59.  
  60.  
  61. function Completed
  62.  
  63. {
  64.  
  65.     [System.Windows.Forms.Application]::DoEvents()
  66.  
  67.     $completedDate = Get-Date
  68.  
  69.     $statusMessage = "$([char]0x2022) Configuring partOne ($oneDate), please wait...`n$([char]0x2022) Configuring partTwo ($twoDate), please wait...`n$([char]0x2022) Configuring partThree ($threeDate), please wait...`n$([char]0x2022) All configuring Completed ($completedDate)!"
  70.  
  71.     $richtextbox1.Text = $statusMessage
  72.  
  73.     Start-Sleep -Seconds 3
  74.  
  75.     Write-Host "Completed"
  76.  
  77.     $formUpdateConfiguration.Close()
  78.  
  79. }
  80.  
  81.  
  82.  
  83. $formUpdateConfiguration_Load = {
  84.  
  85.     loadOne
  86.  
  87.     loadTwo
  88.  
  89.     loadThree
  90.  
  91.     Completed
  92.  
  93. }
I can see the write-host statement coming on screen in the correct flow... but no gui is shown until the end where it blinks, as it shuts down at once.

Best regards
/Flemming

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: How to update GUI when running a function, or a series of functions

Post by jvierra »

You have to add it after you alter a control and not at the beginning of a function. Every line in the function will block. The function will remain blocked until the event that called it exits.

This is why we tend to avoid functions in Windows events. It makes the code harder to follow and is normally not necessary. In your case I see no reason to use functions. They add nothing to the code and make it harder to use, read and understand.

Do not use Start-Sleep in Windows events. It serves no purpose and will block solidly with no hope of the Form receiving any updates. Remember that forms are served by the message loop. Every line of code blocks the message loop. All updates to controls go through the message loop or the dispatcher. This is the hardest thing for non-programmers to understand. Windows is an event based system. Forms are a message dispatch system. Any code executing in a form blocks the message loop. "DoEvents" causes the system to process any queued messages in the message queue. If you do something that changes a property on a control then the DoEvents() call will allow the form to process the change. The DoEvents() must come immediately after the line that makes the change.

See: https://docs.microsoft.com/en-us/dotnet ... mework-4.8

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: How to update GUI when running a function, or a series of functions

Post by jvierra »

Running code in the "Load" event will block the form from being shown until the code finishes executing. The Load event cannot use the DoEvents() method because the form has not yet been loaded. "Load" occurs after all controls have been created but before the form is actually shown. To run code after the form is displayed you must run the code in the "FormShown" event. This event occurs after the form has been displayed.

See the following article on how to use events in forms. Events are not all equal and a good understanding of what events are and how the work and propagate is critical to the coding of forms.

https://docs.microsoft.com/en-us/dotnet ... dows-forms

flho_fvr
Posts: 6
Joined: Mon Feb 03, 2020 12:22 am

Re: How to update GUI when running a function, or a series of functions

Post by flho_fvr »

Hi jvierra

Thanks for your help, I have now come up with a solution that works for me - and thanks for your explanation about the message loop/dispatcher.

Best regards
/Flemming

Locked