首页 > 解决方案 > 从 Powershell 中的 ScheduledJob 触发 NotifyIcon

问题描述

考虑以下函数:

function Notify-Windows(
    [Parameter(Mandatory=$true)]
    [string]$text, 
    [string]$icon="Info",
    [string]$title )
{
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

    $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
    $objNotifyIcon.Icon = [System.Drawing.SystemIcons]::Information
    $objNotifyIcon.BalloonTipIcon = $icon
    $objNotifyIcon.BalloonTipText = $text
    $objNotifyIcon.BalloonTipTitle = $title
    $objNotifyIcon.Visible = $True
    $objNotifyIcon.ShowBalloonTip(10000)
}

就其本身而言,此功能按预期工作,但一旦我将它投入预定的工作,它就不会通知我:

$repeatEvery = New-TimeSpan -Seconds 60
$trigger = New-JobTrigger -Once -At (Get-Date).Date -RepeatIndefinitely -RepetitionInterval $repeatEvery
$options = New-ScheduledJobOption -RunElevated
$msg = "Enter the username and password that will run the task";
$credential = $Host.UI.PromptForCredential("Task username and password",$msg,"$env:userdomain\$env:username",$env:userdomain)

Register-ScheduledJob -Name notifyWindows -ScriptBlock {
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
    $objNotifyIcon.Icon = [System.Drawing.SystemIcons]::Information
    $objNotifyIcon.BalloonTipIcon = "Info"
    $objNotifyIcon.BalloonTipText = "It worked!"
    $objNotifyIcon.BalloonTipTitle = "My Title"
    $objNotifyIcon.Visible = $True
    $objNotifyIcon.ShowBalloonTip(10000)

    Write-Output "The notify-windows function was called and exited properly"
} `
-Trigger $trigger -ScheduledJobOption $options -Credential $credential

从该代码中,我们得到以下输出:

Id         Name            JobTriggers     Command                                  Enabled
--         ----            -----------     -------                                  -------
120        notifyWindows   1               ...                                      True   

现在我们抓住我们关心的工作并运行它:

$sch = Get-ScheduledJob -Id 120
$sch.Run()

作品:

在此处输入图像描述

但是现在让我们等待时间表开始。然后我们将抓住工作并对其进行分析:

> Get-Job | where { $_.Name -eq "notifyWindows" }

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
161    notifyWindows   PSScheduledJob  Completed     True            localhost            ...    

> $job = Get-Job -Id 161
> $job.Output
The notify-windows function was called and exited properly

> $job.Error.Count
0

但是还是……没有通知……

我意识到计划的作业正在单独的 Windows 会话上运行,但是没有任何方法可以强制它通知我吗?或者可能是所有用户?

标签: powershell

解决方案


好吧,不幸的是,经过大量谷歌搜索后,我还没有找到一种方法来完成这项工作System.Windows.Forms.NotifyIcon。话虽如此,我确实找到了一个很好的小包,叫做BurntToast,它工作得很好。

安装:

> Install-Module -Name BurntToast

然后更新的实现如下:

$repeatEvery = New-TimeSpan -Seconds 60
$trigger = New-JobTrigger -Once -At (Get-Date).Date -RepeatIndefinitely -RepetitionInterval $repeatEvery
$options = New-ScheduledJobOption -RunElevated
$msg = "Enter the username and password that will run the task";
$credential = $Host.UI.PromptForCredential("Task username and password",$msg,"$env:userdomain\$env:username",$env:userdomain)

Register-ScheduledJob -Name notifyWindows -ScriptBlock {
    New-BurntToastNotification -Text "It worked!"
    Write-Output "The notify-windows function was called and exited properly"
} `
-Trigger $trigger -ScheduledJobOption $options -Credential $credential 

而已。运行时间为 1 分钟,超级简单,OSS ftw。现在我可以编写工作来监控事情并在其他事情发生时提醒我!尽管找出为什么我的其他方法不起作用或至少如何使它起作用仍然很好。


推荐阅读