Powershell:作为本地系统运行时向登录用户发送 toast 通知

Mac*_*che 4 powershell toast local-system-account

我有一个作为本地系统运行的脚本,它执行一些操作,包括检查用户是否已登录,如果是,它会运行 PowerShell 代码片段来显示 toast 通知,如下所示。

如果 PS 以当前用户身份运行,则可以正常工作。如果它作为 LocalSystem 运行,则当前用户看不到 toast,因为输出发送到会话 0(对于本地系统帐户)。

如果作为本地系统运行并且不请求用户凭据,是否可以向登录用户显示 toast 通知?

Add-Type -AssemblyName System.Windows.Forms 
$global:balloon = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -id $pid).Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) 
$balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Info 
$balloon.BalloonTipText = "$Text"
$balloon.BalloonTipTitle = "$Title" 
$balloon.Visible = $true 
$balloon.ShowBalloonTip($Miliseconds)
Run Code Online (Sandbox Code Playgroud)

And*_*uin 8

介绍

如果在会话 0中以 SYSTEM 用户身份运行而不请求用户凭据,则可以使用 PowerShell 向当前活动登录用户显示 toast 通知。

“背景说明”中有两种解决方案

背景说明

请注意,本节是为这篇文章的所有观众而写的,而不仅仅是最初的提问者。

SYSTEM指同义词NT Authority\SYSTEMLocal System

许多 Windows 服务以SYSTEM用户身份运行,但其他服务则以权限较低的用户身份运行,例如LOCAL SERVICENETWORK SERVICE

对于每个登录用户,都会创建一个从 1 开始编号的 Windows 会话,其中包含用户的窗口。

还会创建一个名为Session 0的附加后台会话,Windows 服务和用户模式驱动程序在其中运行。更多信息请访问以下链接。

会话、桌面和 Windows 工作站

除每用户服务外的所有服务都在会话 0中运行。

如果您正在使用此类脚本的服务,我建议您考虑使用以下两种替代方案之一:

  1. 创建一个会话 1子流程,正如某些服务已经完成的那样。

  2. 使用Windows Task Scheduler来代替在与当前活动用户相同的会话中运行主脚本或通知脚本。该计划任务可以设置为在事件发生时触发。

请注意以下安全警告。Powershell 5 中的脚本可以被中断,从而将控制权交给用户。对于 Powershell 6 及更高版本,可通过使用非交互式选项禁用此行为。

解决方案注释

下面提出两种解决方案来解决原始问题。两者都使用干预程序从会话 0移动到会话 1

两者都会短暂闪烁一个 PowerShell 窗口,这会让用户感到不安并且很难隐藏。下面的链接提供了一些隐藏技巧。

如何在不显示窗口的情况下运行 PowerShell 脚本

以下键入的解决方案需要不带空格的路径。如果给出,则必须使用完整路径。您必须编辑这些路径以适应。

包括测试方法。

第一个解决方案需要PSExec.exe程序。PSTools它是以下链接中可用的一部分。它还用于测试这两种解决方案。

PS工具

第二种解决方案需要该ServiceUI.exe程序。Microsoft Deployment Toolkit (MDT)它是以下链接中可用的一部分。

Microsoft 部署工具包 (MDT)

ServiceUI.exe程序埋藏在MDT安装目录中,如下所示。

Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64\ServiceUI.exe

我将其复制到E:\Programs\MDT\ServiceUI.exe以便在 PowerShell 中使用更简单

需要脚本

气球测试.ps1

$Miliseconds=50000
$Text="Hi"
$Title="Test"

Add-Type -AssemblyName System.Windows.Forms 
$global:balloon = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -id $pid).Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) 
$balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Info 
$balloon.BalloonTipText = "$Text"
$balloon.BalloonTipTitle = "$Title" 
$balloon.Visible = $true 
$balloon.ShowBalloonTip($Miliseconds)
Run Code Online (Sandbox Code Playgroud)

我是谁会话.ps1

whoami
$Session=(Get-Process -PID $pid).SessionID
echo "Session=$Session"
Run Code Online (Sandbox Code Playgroud)

测试设置

启动一个cmd.exe窗口作为Administrator.

以下命令将提供 SYSTEM 用户会话 0 PowerShell 执行环境,如图所示。

E:\Programs\PSTools\psexec -s powershell.exe -file e:\test\WhoAmISession.ps1
Run Code Online (Sandbox Code Playgroud)

PS执行会话

解决方案1:PSExec.exe

PowerShell要在以SYSTEM用户身份运行时显示 Toast 通知,请Session 0 使用以下命令。如果当前活动登录用户正在使用,这将显示 Toast 通知Session 1。其他会议需要进行一些修改。

E:\Programs\PSTools\psexec -s -i 1 C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file e:\test\BalloonTest.ps1
Run Code Online (Sandbox Code Playgroud)

要测试,请启动一个"cmd.exe"窗口"Administrator"并输入以下命令。如果当前活动登录用户正在使用,这将显示 Toast 通知,Session 1如图所示。

E:\Programs\PSTools\psexec -s powershell.exe E:\Programs\PSTools\psexec -s -i 1 C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file e:\test\BalloonTest.ps1
Run Code Online (Sandbox Code Playgroud)

PSExec 气球测试

解决方案2:ServiceUI.exe

PowerShell要在以SYSTEM用户身份运行时显示 Toast 通知,请Session 0 使用以下命令。这将向当前活动登录用户显示 Toast 通知。

E:\Programs\MDK\ServiceUI.exe C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file e:\test\BalloonTest.ps1
Run Code Online (Sandbox Code Playgroud)

要测试,请启动一个"cmd.exe"窗口"Administrator"并输入以下命令。这将向当前活动的登录用户显示 Toast 通知,如图所示。

E:\Programs\PSTools\psexec -s powershell.exe E:\Programs\MDK\ServiceUI.exe C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file e:\test\BalloonTest.ps1
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述