1

I have a question regarding event handlers (Register-ObjectEvent). Here's my code:

Import-Module "$PSScriptRoot\Lib\Ookii.Dialogs.Winforms.dll"

$OKButton     = [Ookii.Dialogs.WinForms.TaskDialogButton]("Ok")
$NOButton     = [Ookii.Dialogs.WinForms.TaskDialogButton]("No")
$CancelButton = [Ookii.Dialogs.WinForms.TaskDialogButton]("Cancel")
$HelpButton   = [Ookii.Dialogs.WinForms.TaskDialogButton]("Help")

$OokieTaskDialog = New-Object Ookii.Dialogs.WinForms.TaskDialog
$OokieTaskDialog.Buttons.Add($OKButton)
$OokieTaskDialog.Buttons.Add($NOButton)
$OokieTaskDialog.Buttons.Add($CancelButton)
$OokieTaskDialog.Buttons.Add($HelpButton)

$OokieTaskDialog.MainInstruction      = "Main Instruction"
$OokieTaskDialog.Content              = "Eiusmod cupidatat amet officia ut cillum anim proident. Aliqua aliqua ullamco reprehenderit velit est eiusmod et aute."
$OokieTaskDialog.ExpandedInformation  = "Wozarlov, Marvin Houston, (870) 487-7980"
$OokieTaskDialog.Footer               = "This is the footer text <a href=`"https://www.google.com`">More Info</a>"
$OokieTaskDialog.FooterIcon           = [Ookii.Dialogs.WinForms.TaskDialogIcon]::Information
$OokieTaskDialog.EnableHyperlinks     = $true

Register-ObjectEvent -InputObject $OokieTaskDialog -EventName HyperlinkClicked -Action { Write-Host "Link Clicked" }

$OokieTaskDialog.WindowTitle              = "Window Title"
$OokieTaskDialog.Width                    = 300
$OokieTaskDialog.AllowDialogCancellation  = $true
$OokieTaskDialog.MainIcon                 = [Ookii.Dialogs.WinForms.TaskDialogIcon]::Warning

$Result = $OokieTaskDialog.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true}))
$Result

Specifically: Register-ObjectEvent -InputObject $OokieTaskDialog -EventName HyperlinkClicked -Action { Write-Host "Link Clicked" }

The event handler works, but it only displays the results ("Link Clicked") AFTER the dialog has closed. How do I get an event handler to respond immediately when the trigger conditions have been met?

For instance, if I click the hyperlink in the footer 10 times, and then click the OK button, the console prints "Link Clicked" 10 times.

I want to print "Link Clicked" immediately when the hyperlink is clicked.

How can I register an event that fires immediately? What am I doing wrong?

fmotion1
  • 237
  • 4
  • 12
  • From https://social.technet.microsoft.com/Forums/windows/en-US/b12ad0b9-ccd2-4c86-9a1c-a07fdab6605f/eventhandling-on-powershellgui-systemwindowsforms?forum=winserverpowershell - “Don't use the PowerShell register-objectevent as it will not work in the way that you think it would. It is going to be fighting the UI for the thread and never actually fire when you click the checkbox. Instead, use the control's own event handler to make it work for you.” – mclayton Apr 28 '22 at 06:38
  • I am pretty sure that the `Register-ObjectEvent` fires immediately (it just doesn't show, you might confirm this by e.g. writing the time). I am not known with the Ookii module, but in general: I would use the **WinForms events** (as [OnClick](https://learn.microsoft.com//dotnet/api/system.windows.forms.control.onclick)) **for WinForms**. – iRon Apr 28 '22 at 06:39

1 Answers1

2

ShowDialog run on the same thread than the listener created through Register-ObjectEvent. It won't process anything until the dialog is closed.

To have a script block directly handle a .NET event, call the object's Add-Event() method.

$OokieTaskDialog.Add_HyperlinkClicked({ Write-Host "Link Clicked" })

Additional references:

This mklement0 excellent answer: How to add an Event Action handler in Powershell

Excerpt

C# offers syntactic sugar in the form of operators += and -= for attaching and detaching event-handler delegates, which look like assignments, but are in reality translated to add_() and remove_() method calls.

PowerShell offers no such syntactic sugar for attaching/removing event handlers, so the methods must be called directly.

This very complete answer by iRon: Powershell: Job Event Action with Form not executed

Excerpt:

Even if there are multiple threads setup, there are two different 'listeners' in one thread. When your script is ready to receive form events (using ShowDialog or DoEvents) it can’t listen to .NET events at the same time. And visa versa

Both of these answers provide a lot more insights and references links themselves.

Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39