您已经有代码来设置
NotifyIcon
...
$Main_Tool_Icon.Icon = $icon
…并定义要使用的图标。。。
# Choose an icon to display in the systray
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Current_Folder/icons/online.ico")
# use this icon when notepad is not running
# $icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Current_Folder/icons/offline.ico")
…并定期测试
Notepad
正在运行并正确响应。。。
$timer.Add_Tick({
if ($Label){
$Label.Text = if (Test-Notepad) { "Notepad is running" } else { "Notepad is NOT running" }
}
})
你只需要把它们和一些额外的调整结合起来。。。
-
用描述性名称将每个图标存储在自己的变量中,以便在它们之间轻松切换。
-
$Main_Tool_Icon
需要在
create_taskbar_menu
这样就可以在
OnMenuItem1ClickEventFn
. 我将创建和初始化移到调用
创建任务栏菜单
,但也可以在
创建任务栏菜单
或者其他功能。
最后看起来像这样。。。
# Choose an icon to display in the systray
$onlineIcon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Current_Folder/icons/online.ico")
# use this icon when notepad is not running
$offlineIcon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Current_Folder/icons/offline.ico")
$Main_Tool_Icon = New-Object System.Windows.Forms.NotifyIcon
$Main_Tool_Icon.Text = "Icon Text"
$Main_Tool_Icon.Icon = if (Test-Notepad) { $onlineIcon } else { $offlineIcon }
$Main_Tool_Icon.Visible = $true
create_taskbar_menu
…还有这个。。。
$timer.Add_Tick({
if ($Label){
# Change the text and icon with one test
$Label.Text, $Main_Tool_Icon.Icon = if (Test-Notepad) {
"Notepad is running", $onlineIcon
} else {
"Notepad is NOT running", $offlineIcon
}
}
})
您将看到一个图标是基于
Test-Notepad
都是什么时候
$Main\u工具\u图标
当
Tick
事件已引发。
至于处理
$timer
什么时候
$Form
正在关闭。。。
$Form.Add_Closing({ $timer.Dispose() })
……就是这样
几乎
一个合适的地方,但是。。。
另外,在
OnMenuItem4ClickEventFn
你在打电话吗
$window.Close()
尽管
$window
我想你的意思是
$Form.Close()
. 另一个我认为稍微干净一点的方法是点击
Exit
菜单项
exit the Windows Forms application loop
...
function OnMenuItem4ClickEventFn () {
$Main_Tool_Icon.Visible = $false
[System.Windows.Forms.Application]::Exit()
}
…然后您可以将清理/拆卸代码放入
finally
在脚本末尾阻止。。。
try
{
# This call returns when [System.Windows.Forms.Application]::Exit() is called
[System.Windows.Forms.Application]::Run($appContext)
}
finally
{
# $timer would also have to be defined at the script scope
# (outside of OnMenuItem1ClickEventFn) for this to work
$timer.Dispose()
# $Form, $Label, $Main_Tool_Icon, $onlineIcon, etc. would all be candidates for disposal...
# Exit the entire PowerShell process
Stop-Process $pid
}
以下是完整的代码,其中包括上述更改,并为我工作。。。
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
function Test-Notepad {
[bool](Get-Process -Name 'notepad' -ErrorAction SilentlyContinue)
}
function OnMenuItem1ClickEventFn () {
$timer.Start()
# Build Form object
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "My Form"
$Form.Size = New-Object System.Drawing.Size(200,200)
$Form.StartPosition = "CenterScreen"
$Form.Topmost = $True
$Form.Add_Closing({ $timer.Dispose() }) # Dispose() also stops the timer.
$Form.Controls.Add($Label) # Add label to form
$form.ShowDialog()| Out-Null # Show the Form
}
function OnMenuItem4ClickEventFn () {
$Main_Tool_Icon.Visible = $false
[System.Windows.Forms.Application]::Exit()
}
function create_taskbar_menu{
# Create menu items
$MenuItem1 = New-Object System.Windows.Forms.MenuItem
$MenuItem1.Text = "Menu Item 1"
$MenuItem2 = New-Object System.Windows.Forms.MenuItem
$MenuItem2.Text = "Menu Item 2"
$MenuItem3 = New-Object System.Windows.Forms.MenuItem
$MenuItem3.Text = "Menu Item 3"
$MenuItem4 = New-Object System.Windows.Forms.MenuItem
$MenuItem4.Text = "Exit"
# Add menu items to context menu
$contextmenu = New-Object System.Windows.Forms.ContextMenu
$Main_Tool_Icon.ContextMenu = $contextmenu
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($MenuItem1)
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($MenuItem2)
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($MenuItem3)
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($MenuItem4)
$MenuItem4.add_Click({OnMenuItem4ClickEventFn})
$MenuItem1.add_Click({OnMenuItem1ClickEventFn})
}
$Current_Folder = split-path $MyInvocation.MyCommand.Path
# Add assemblies for WPF and Mahapps
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | out-null
[System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | out-null
[System.Reflection.Assembly]::LoadWithPartialName('System.Drawing') | out-null
[System.Reflection.Assembly]::LoadWithPartialName('WindowsFormsIntegration') | out-null
# [System.Reflection.Assembly]::LoadFrom("Current_Folder\assembly\MahApps.Metro.dll") | out-null
# Choose an icon to display in the systray
$onlineIcon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Current_Folder/icons/online.ico")
# use this icon when notepad is not running
$offlineIcon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Current_Folder/icons/offline.ico")
$Main_Tool_Icon = New-Object System.Windows.Forms.NotifyIcon
$Main_Tool_Icon.Text = "Icon Text"
$Main_Tool_Icon.Icon = if (Test-Notepad) { $onlineIcon } else { $offlineIcon }
$Main_Tool_Icon.Visible = $true
# Build Label object
$Label = New-Object System.Windows.Forms.Label
$Label.Name = "labelName"
$Label.AutoSize = $True
# Initialize the timer
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000
$timer.Add_Tick({
if ($Label){
$Label.Text, $Main_Tool_Icon.Icon = if (Test-Notepad) {
"Notepad is running", $onlineIcon
} else {
"Notepad is NOT running", $offlineIcon
}
}
})
create_taskbar_menu
# Make PowerShell Disappear - Thanks Chrissy
$windowcode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
$asyncwindow = Add-Type -MemberDefinition $windowcode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru
$null = $asyncwindow::ShowWindowAsync((Get-Process -PID $pid).MainWindowHandle, 0)
# Use a Garbage colection to reduce Memory RAM
# https://dmitrysotnikov.wordpress.com/2012/02/24/freeing-up-memory-in-powershell-using-garbage-collector/
# https://docs.microsoft.com/fr-fr/dotnet/api/system.gc.collect?view=netframework-4.7.2
[System.GC]::Collect()
# Create an application context for it to all run within - Thanks Chrissy
# This helps with responsiveness, especially when clicking Exit - Thanks Chrissy
$appContext = New-Object System.Windows.Forms.ApplicationContext
try
{
[System.Windows.Forms.Application]::Run($appContext)
}
finally
{
foreach ($component in $timer, $form, $Main_Tool_Icon, $offlineIcon, $onlineIcon, $appContext)
{
# The following test returns $false if $component is
# $null, which is really what we're concerned about
if ($component -is [System.IDisposable])
{
$component.Dispose()
}
}
Stop-Process -Id $PID
}