2010-02-01 9 views
8

Versione corta: Penso di aver bisogno di aiuto per utilizzare correttamente gli eventi in PowerShell che vengono richiamati come risultato di un messaggio di Windows per eliminare l'icona di un suggerimento del fumetto.Visualizzazione corretta di un suggerimento del fumetto del vassoio in PowerShell

Versione lunga:

Ho un comando di PowerShell di lunga durata (una build) che vorrei essere avvisato quando completa tramite un tooltip palloncino nell'area di notifica/comunicazione.

Sono stato in grado di creare uno script Write-BalloonTip (in basso) che fa all'incirca quello che voglio. L'unico problema è che, as sometimes happens with tray icons, l'icona del vassoio non scompare fino a quando non lo passo con il mouse. Riutilizzando la stessa variabile globale per rappresentare lo NotifyIcon, sono in grado di riutilizzare questo script e mantenerlo in modo che rimanga solo un'icona nell'area di notifica del sistema (fino a quando non lo faccio scorrere sopra). Questo sembra ancora un hack. Ho provato ad aggiungere un gestore di eventi in modo che fosse notificato sull'evento BalloonTipClosed e quindi smaltirlo lì. Nel gestore dell'evento, ho provato tutte e tre le tecniche che ho visto suggerite per eliminare l'icona persistente senza successo.

La parte fastidiosa è che un semplice .Dispose sembra funzionare sulle chiamate successive dello script, portandomi a pensare che il blocco dello script di eventi non venga chiamato affatto.

Ho verificato che BalloonTipClosed viene chiamato dopo che il suggerimento si attenua in un'app separata di WinForms.

Mi manca qualcosa di base? Ogni aiuto è molto apprezzato. Grazie!

Ecco il codice per "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); 
+0

Forse un po 'fuori dal comune, ma ho trovato Growl molto utile per Windows. Jaykul ha scritto una libreria che racchiude la funzionalità. C'è anche un plugin che ti avvisa quando il tuo build/ricostruzione finisce. Potresti trovarlo qui: http://huddledmasses.org/more-growl-for-windows-from-powershell/ (non so se sia l'ultima versione) – stej

+0

Hai risolto? – stej

+0

Non proprio, non c'era una soluzione rapida, quindi continuiamo a riciclare un'unica icona globale. È una soluzione ragionevole fino a quando non siamo motivati ​​a risolverlo effettivamente gestendo il problema STA. –

risposta

2

Penso che è necessario per eseguire questo codice in un thread STA. PowerShell (v2 mostrato qui) viene eseguito in un thread MTA di 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 
+0

Penso che questo si avvicini al nocciolo del problema in quanto sembra che l'evento di notifica venga inviato tramite un messaggio di Windows. Qualche idea su come farlo nel modo giusto? Sembra che un Invoke-Apartment dovrebbe funzionare, ma non riesco a farlo funzionare. –

1

mi consiglia di utilizzare il registro-ObjectEvent per sottoscrivere l'evento BalloonTipClosed. Questo è emerso di recente nel another SO post. Controlla.

+1

Penso che il nocciolo del problema sia il problema STA perché l'evento non viene generato a meno che non si trovi su un thread STA. –

+0

Il debugger JIT segnala "System.Management.Automation.PSInvalidOperationException: non è disponibile spazio di esecuzione per l'esecuzione di script in questo thread. È possibile fornire uno nella proprietà DefaultRunspace del tipo System.Management.Automation.Runspaces.Runspace" sul BallonTipClosed evento quindi l'evento è stato sollevato. È possibile creare un Runspace in PS, ma è molto più rapido utilizzare Register-ObjectEvent – Monso

Problemi correlati