我遇到一种情况,我需要一个计划任务来运行脚本,检查某些证书是否即将到期,然后通知用户。我选择使用Windows Forms NotifyIcon对象,因为我可以弹出一个看起来已集成到操作系统中的漂亮的小气球。我希望它在用户点击图标时显示一个MsgBox(好吧,我希望它在点击图标或气球时执行它,但是现在我会在图标上找到它)。
问题在于我无法让脚本等待用户点击图标,或者如果我设置循环以使脚本等待,我似乎无法让脚本退出用户单击图标时的循环。如果脚本只是退出而没有等待,则图标消失,带上气球,所以用户在屏幕上看到一个图标和气球闪光,并且在它们可以阅读或与之交互之前消失。这是一个展示问题的简化版本(您需要将图标路径更改为系统上的有效.ico文件)。
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")|Out-Null
Function Show-MsgBox ($Text,$Title="",[Windows.Forms.MessageBoxButtons]$Button = "OK",[Windows.Forms.MessageBoxIcon]$Icon="Information"){
[Windows.Forms.MessageBox]::Show("$Text", "$Title", [Windows.Forms.MessageBoxButtons]::$Button, $Icon) | ?{(!($_ -eq "OK"))}
}
#Create Notification Icon
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = "Click Me!"
$objNotifyIcon.BalloonTipTitle = "I'm a title"
$objNotifyIcon.Text = "Click Me!"
$objNotifyIcon.Icon = "C:\temp\vsmartcard.ico"
$NotDone = $true
$objNotifyIcon.add_click({Show-MsgBox -text "User Clicked Icon"; $Global:NotDone = $false})
$objNotifyIcon.Visible = $true
$objNotifyIcon.ShowBalloonTip(10000)
While($NotDone){
"`$NotDone = $NotDone`nSleeping for 3 seconds"
Start-Sleep -Seconds 3
}
$objNotifyIcon.Visible = $False
$objNotifyIcon.Dispose()
奇怪的是,如果我点源它,它会按预期工作,但如果我只运行脚本则不行。
我已尝试注册事件而不是使用add_click
方法并使用Wait-Event
cmdlet,但它从未注册事件发生,它或者永远坐在那里等待事件,如果我包括超时,它等待它过期,然后完成脚本并退出(在这种情况下,如果用户在超时的15秒内没有注意到它,可能永远不会看到我的通知)。我尝试过的代码如下(我在几年前Keith Hill的SO回答中找到的代码的修改版本):
Register-ObjectEvent $objNotifyIcon BalloonTipClicked -SourceIdentifier event_BalloonTipClicked -Action {
Show-MsgBox -Text $Text -Title $Title
Unregister-Event -SourceIdentifier $event.SourceIdentifier -Force
Remove-Job $event.SourceIdentifier -Force
$objNotifyIcon.Visible = $False
}
Register-ObjectEvent $objNotifyIcon Click -SourceIdentifier event_Click -Action {
Show-MsgBox -Text $Text -Title $Title
Unregister-Event -SourceIdentifier $event.SourceIdentifier -Force
Remove-Job $event.SourceIdentifier -Force
$objNotifyIcon.Visible = $False
}
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(10000)
wait-event
我尝试在Break
事件脚本块中包含Exit
和Click
,但他们只是犯了错误。
答案 0 :(得分:1)
while($Global:NotDone) { ... }
这样它就会引用事件中已经引用的相同变量。
问题是没有什么可以等待这个事件,正如你所推测的那样。但是尝试添加循环将不起作用,因为你只有一个线程,现在它陷入沉睡和循环。
您可能需要为此使用事件,然后您需要等待事件,而不仅仅是睡觉。
我找到a good example of this on powershell.com:
param
(
$msg = "For the latest updates check our intranet website. Please click in the balloon.",
$title = "News",
$icon = "None",
$timeout=1
)
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | out-null
$Balloon = new-object System.Windows.Forms.NotifyIcon
$Balloon.Icon = [System.Drawing.SystemIcons]::Information
$Balloon.Visible = $true;
$Balloon.ShowBalloonTip($timeout, $title, $msg, $icon);
Unregister-Event -SourceIdentifier click_event -ErrorAction SilentlyContinue
Register-ObjectEvent $Balloon BalloonTipClicked -sourceIdentifier click_event -Action {
$ie = New-Object -com InternetExplorer.Application
$ie.navigate2("https://intranet.mydomain.com")
$ie.visible = $true
} | Out-Null
Wait-Event -timeout 15 -sourceIdentifier click_event > $null
Remove-Event click_event -ea SilentlyContinue
Unregister-Event -SourceIdentifier click_event -ErrorAction SilentlyContinue
$Balloon.Dispose()
这里Wait-Event
正在等待。
你说你有这种方法的问题。您是否可以将该代码编辑到问题中?