开发者

Properly displaying a tray balloon tooltip in PowerShell

开发者 https://www.devze.com 2022-12-19 00:00 出处:网络
Short version: I think I need help with properly using events in PowerShell that are invoked as a result of a Windows Message to get rid of a balloon tooltip\'s icon.

Short version: I think I need help with properly using events in PowerShell that are invoked as a result of a Windows Message to get rid of a balloon tooltip's icon.

Long Version:

I have a long-running PowerShell command (a build) that I would like to be notified when it completes via a balloon tooltip in the system tray/notification area.

I was able to create a Write-BalloonTip script (below) that does roughly what I want. The only problem is that, as sometimes happens with tray icons, the tray icon doesn't disappear until I mouse over it. By re-using the same global variable to represent the NotifyIcon, I'm able to re-use this script and keep it so that only one system tray icon remains (until I mouse over it). This still feels like a hack. I tried to add an event handler so that it'd be notified on the BalloonTipClosed event and then dispose of it there. In the event handler, I tried all three techniques I've seen suggested for getting rid of the lingering icon to no av开发者_StackOverflow中文版ail.

The annoying part is that a simple .Dispose seems to work on subsequent calls of the script, leading me to think that the event script block isn't being called at all.

I've verified that BalloonTipClosed gets called after the tip fades away in a separate WinForms app.

Am I missing something basic? Any help is much appreciated. Thanks!

Here's the code for "Write-BalloonTip.ps1":

param
(
    $text,
    $title = "",
    $icon = "Info",
    $timeout=15000
)

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | out-null

if ($global:writeBalloonTipIcon)
{
    # This gets rid of the previous one
    $global:writeBalloonTipIcon.Dispose()
}

$global:writeBalloonTipIcon = new-object System.Windows.Forms.NotifyIcon 
$global:writeBalloonTipIcon.Icon = [System.Drawing.SystemIcons]::Information

# FIXME: This *should* cleanup the icon after it's done, but it doesn't seem to work
$global:writeBalloonTipIcon.add_BalloonTipClosed(
  {
    # this *should* work, but it's not. What am I missing?
    $global:writeBalloonTipIcon.Icon = $null; 
    $global:writeBalloonTipIcon.Visible = $false; 
    $global:writeBalloonTipIcon.Dispose();
  });

$global:writeBalloonTipIcon.Visible = $true;
$global:writeBalloonTipIcon.ShowBalloonTip($timeout, $title, $text, $icon);


I think you need to execute this code in an STA thread. PowerShell (v2 shown here) executes in an MTA thread by default:

PS U:\> [System.Threading.Thread]::CurrentThread


ManagedThreadId    : 5
ExecutionContext   : System.Threading.ExecutionContext
Priority           : Normal
IsAlive            : True
IsThreadPoolThread : False
IsBackground       : False
ThreadState        : Running
ApartmentState     : MTA
CurrentUICulture   : en-US
CurrentCulture     : en-US
Name               : Pipeline Execution Thread


I would recommend using the Register-ObjectEvent to subscribe to the BalloonTipClosed event. This came up recently in another SO post. Check it out.

0

精彩评论

暂无评论...
验证码 换一张
取 消