0

I created a winforms gui for my ps script.
By clicking on start button the script takes data from a list of addresses, modifies the body text and the object and sends the email showing a progressbar.

# FORM BUTTON START
function ButtonStart_Click {

    $script:CancelLoop = $false

    $ProgressBar1.Visible = $true
    $progressbar1.Value = 0
    $LabelCounter.visible = $true

    $ButtonStart.Enabled = $false
    $ButtonStop.Enabled = $true
    $TextBoxSubject.ReadOnly = $true
    $TextBoxTimeout.ReadOnly = $true

    # =============================================================
    # LOOP DATA OBJECT
    # =============================================================
    $Counter = 0
    $ErrorCounter = 0
    $Timeout = 0

    foreach ($Row in $ExcelData) {

        [System.Windows.Forms.Application]::DoEvents()

        # =============================================================
        # Customize mail subject
        # =============================================================
        $Id = Get-Random -Minimum 99999999
        $Subject = ReplaceChars $TextBoxSubject.Text $Id
        $MailSettings.Subject = $Subject

        # Check timeout input
        if ($TextBoxTimeout.Text -match '^[0-9]+$'){
            $Timeout = [int]$TextBoxTimeout.Text
        }

        # =============================================================
        # Customize body
        # =============================================================
        $BodyHTML = ReplaceChars $Body $Row

        # =============================================================
        # PROGRESSBAR
        # =============================================================        
        if ($script:CancelLoop -eq $true){
            $progressbar1.Value = 0
            break
        }

        # Calculate The Percentage Completed 
        $Counter++ 
        [Int]$Percentage = ($Counter/$ExcelData.Count)*100 
        $ProgressBar1.Value = $Percentage 
        $LabelCounter.Text = "Invio $Counter di " +$ExcelData.Count 

        # =============================================================
        # SEND EMAIL
        # =============================================================     
        if ($Row.Email) {

            try {
                Send-MailMessage -to $Row.Email -Body $BodyHTML -BodyAsHtml @MailSettings -ErrorAction STOP

                if ($Timeout -gt 0) {
                    Sleep $Timeout
                }
             }
            catch {
                Log-Write $ErrorLogFile $_.Exception.Message
                $ErrorCounter++;
            }

        }

    }

    if ($Counter -eq $ExcelData.Count) {
        [System.Windows.Forms.MessageBox]::Show("OK!","Info","OK","Information")
        $ButtonStop.Enabled = $false

        # Show Errors Popup
        if ($ErrorCounter -gt 0) {
            [System.Windows.Forms.MessageBox]::Show("Error !","Error","OK","Error")
        }
        $Form.close()
    }


# FORM BUTTON STOP
function ButtonStop_Click {
    $script:CancelLoop = $true
    $ProgressBar1.Visible = $false 
    $ProgressBar1.Value = 0
    $LabelCounter.Visible = $false
    $TextBoxSubject.ReadOnly = $false
    $TextBoxSubject.Text = ""
    $TextBoxTimeout.ReadOnly = $false
}

My problem is that during the execution of the script it seems that the GUI freezes.
Even the stop button sometimes despite being enabled does not seem to interact.

I would like to try launching the loop for generating and sending mail in the background (solving the freeze?), keeping the progressbar and command button in main windows but unfortunately I could not do it (I lost control of the background job). Can you give me a hand to do this?
Thank you

Paolo Rossi
  • 2,490
  • 9
  • 43
  • 70
  • you can use Threads or Background Process Worker for this scenario. – Nirav Mistry Jun 17 '19 at 11:20
  • could you explain me how? thank you – Paolo Rossi Jun 17 '19 at 12:43
  • what you are looking for are runspaces. They are a way to implement multithreading in powershell. But that is a very broad field and the reason why i rewrote my entire script in WPF. WinForms is realy bad when it comes to getting back data from the other thread. (WPF works well with datacontext). Boe Prox has written some very usefull guids for using powershell + runspaces. ( [here is one](https://learn-powershell.net/2012/10/14/powershell-and-wpf-writing-data-to-a-ui-from-a-different-runspace/) ) [Here](https://stackoverflow.com/a/53498448/10223991) is something on SO. – T-Me Jun 17 '19 at 14:52
  • I will try to follow what you suggested. thank you – Paolo Rossi Jun 17 '19 at 16:10

0 Answers0