Windows PowerShell每周提示(42):在通知区域显示一条消息
老实说,当脚本作家处理组成Windows界面的图形用户元素时经常上当受骗。无可否认编写VBScritpt的人在使用HTA(HTML应用程序)时做了很多酷事。然而,HTA限制了能在Web页面中使用的控件及用户界面元素。正如HTA有可能达到的酷那样,这些程序(及编写他们的人)还没有能够涉及到在羽翼丰满的编程语言中真正酷的用户界面元素。
例如,脚本专家经常被问及编写VBscript的人如何在通知区域(位于屏幕右下角的小区域,操作系统及程序的消息经常会在这里出现)显示一条消息。每一次被问及此问题时,我们的回答总是一样的:抱歉,无法实现。
噢,如果编写Windows PowerShell脚本的人问起同样问题的话……
怎么了?为什么我们希望编写Windows PowerShell脚本的人询问这个问题?这很简单:因为,这样的话,我们会有一个比较好的回答。事实证明,你能使用.NET Framework在通知区域内显示消息。因为Windows PowerShell能完全访问.NET Framework,这就意味着你能在通知区域内显示消息。
不,我们没有在开玩笑。真的能使用Windows PowerShell在通知区域内显示消息。如果你不能的话,我们就不会毫无理由的将类似以下的脚本放在此处:
| [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon $objNotifyIcon.Icon = "C:\Scripts\Forms\Folder.ico" $objNotifyIcon.BalloonTipIcon = "Error" $objNotifyIcon.BalloonTipText = "A file needed to complete the operation could not be found." $objNotifyIcon.BalloonTipTitle = "File Not Found" $objNotifyIcon.Visible = $True $objNotifyIcon.ShowBalloonTip(10000) |
让我们证明下这个脚本是如何工作的,并让你知道如何在你的自己脚本中使用这些代码。最开始,我们使用以下这行代码来加载.NET Framework类 System.Windows.Forms的一个实例:
| [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") |
如果万一你对这行代码开始处的[void]感到疑惑的话,那么它的作用只是避免在加载System.Windows.Form类时出现状态信息。如果不使用[void],那么当我们每次运行脚本时将看到以下信息:
| GAC Version Location--- ------- --------True v2.0.50727 C:\WINDOWS\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c561934e089\System.Windows.For... |
不管这信息对你而言是否值得一读,只是我们真的不需要每次运行脚本都显示该这信息。
在加载System.Windows.Forms类以后我们使用New-Object cmdlet来创建System.Windows.Forms.NotifyIcon类的实例。如你猜测的那样,这是让我们可以配置及在通知区域显示信息的.NET类。
| $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon |
接下来我们需要定义通知的几个属性。尤其是,我们需要对以下项目赋值:
| 属性 | 描述 |
| Icon | 这是在通知区域出现的图标。图标必须为16像素宽16像素高。如果你有图标编辑软件那么你能自己创建图标,如果你没有的话那么在你的计算机(或者互联网)上搜索.ICO文件。请确保在你对Icon属性赋值时你指定了完整路径:$objNotifyIcon.Icon = "C:\Scripts\Forms\Folder.ico". |
| BalloonTipIcon | 这是在通知内显示的图标(看下面的插图)。你能在以下有操作系统提供的图标中选择:Info、Warning及Error。在我们的例子中,我们将BalloonTipIcon设置为Error。 |
| BalloonTipText | 真正被显示的信息。对这个脚本而言我们将BalloonTipText设置为“A file needed to complete the operation could not be found.” |
| BalloonTipTitle | 通知的标题。例如,File Not Found。 |
更形象的来说是这样:
无论相信与否,我们几乎已经完成了。在设置Visible属性为真($True)后,我们要做的是调用ShowBalloonTip方法来显示通知:
| $objNotifyIcon.ShowBalloonTip(10000) |
有几个关于ShowBalloonTip方法的注意事项。一件事是,你注意到我们向ShowBallonTip传递了10000这个参数了么?好的,理论上,这数字表明了我们想要通知在自动消失之前在屏幕上停留的时间。因为一秒由1000毫秒组成,10000这这意味着,理论上,我们想要通知在屏幕上停留10秒,然后匆匆道别。这看上去很简单。那么为什么我们要说“理论上”?这是因为受到一些外部因素影响。例如,当在通知区域显示通知时,操作系统加上了相关限制。通常来说,通知必须在屏幕上停留至少10秒但不超过30秒。这是什么意思?让我们这样解释:假设你向ShowBalloonTip传递了300000这个参数值,认为这将使通知在屏幕上显示5分钟(300000毫秒)。尽管实际上,通知在屏幕上不会待那么久。操作系统将会在这之前打断它。同样的,如果你将参数设为1,并认为通知将在屏幕上显示1毫秒然后消失。这也将不会正常运行:Windows将会确保通知消失之前已经显示了允许显示时间的最小值。
不仅是这样,时间也取决于在计算机上正在发生的活动。如果系统处于空闲状态,那么倒计时将不会开始直到发生了一些活动行为。在这种情况下,通知可能在显示了几小时后才会消失。
| 注意.当然你能通过点击来结束一个通知。也就是说,我们应当指出,任何超时了的通知将会消失,但是图标将仍然显示在通知区域,知道你的鼠标划过该区域。然后,如果你通过点击关闭了通知那么图标也会消失。 |
不管通知将会在屏幕上停留多少时间,它看上去都像是这样的:
不坏吧?
另一件需要记住的是,在通知显示期间,你的脚本将继续运行。脚本不会自动暂停来等待通知消失。这应当没什么问题,只是你应当注意。
下面是一个酷提示:你能在任意时间改变通知。例如,下面有一个脚本来显示文件正在从C:\Windows文件夹中提取的通知。一旦Get-ChildItem完成了收集文件的工作,BalloonTipText及BalloonTipTitle属性将被更新,来说明文件已经提取完成。当Visible属性设为真并且ShowBallonTip方法被调用时,这个“新的”通知将会替代前一个通知。
下面是代码:
| [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon $objNotifyIcon.Icon = "C:\Scripts\Forms\Folder.ico" $objNotifyIcon.BalloonTipIcon = "Info" $objNotifyIcon.BalloonTipText = "Retrieving files from C:\Windows." $objNotifyIcon.BalloonTipTitle = "Retrieving Files" $objNotifyIcon.Visible = $True $objNotifyIcon.ShowBalloonTip(10000) Get-ChildItem C:\Windows $objNotifyIcon.BalloonTipText = "The script has finished running." $objNotifyIcon.BalloonTipTitle = "Files retrieved." $objNotifyIcon.Visible = $True $objNotifyIcon.ShowBalloonTip(10000) |
这是编写系统管理脚本的人几年来梦寐以求的事。
本周的专栏也到此结束了。脚本编辑已经等得不耐烦了,并在想我们到底什么时候将本文交付编辑。别担心,脚本编辑,我们刚想这么做。
下周见。
英文原文
http://www.microsoft.com/technet/scriptcenter/resources/pstips/may08/pstip0523.mspx