[英]Showing currently logged in user in a PowerShell running from a RMM Software as SYSTEM
[英]Powershell: Send a toast notification to logged user when running as Local System
我有一個作為本地系統運行的腳本,它執行一些操作,包括檢查它是否是用戶登錄,如果是,它運行 PowerShell 片段以顯示 toast 通知,如下所示。
如果 PS 以當前用戶身份運行,它就可以正常工作。 如果它作為 LocalSystem 運行,則當前用戶看不到 toast,因為發送 output Session 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)
如果在Session 0中以 SYSTEM 用戶身份運行而無需請求用戶的憑據,則可以使用 PowerShell 向當前活動的登錄用戶顯示 toast 通知。
遵循“背景說明”的兩種解決方案
請注意,此部分是為這篇文章的所有查看者而寫的,而不僅僅是最初的提問者。
SYSTEM
指的是同義詞NT Authority\SYSTEM
和Local System
。
許多 Windows 服務以SYSTEM
用戶身份運行,盡管其他服務以具有較少權限的用戶身份運行,例如LOCAL SERVICE
和NETWORK SERVICE
。
對於每個登錄的用戶,一個 Windows session 從 1 開始創建,其中包含用戶的 windows。
另一個背景 session 稱為Session 0還創建了 Windows 服務和用戶模式驅動程序在其中運行。更多信息在以下鏈接。
除Per-User Services之外的所有服務都在Session 0中運行。
如果您正在為此類腳本使用服務,我建議您使用以下兩種替代方法之一:
創建一個Session 1子進程,正如某些服務已經完成的那樣。
改用Windows Task Scheduler
在與當前活動用戶相同的 session 中運行主腳本或通知腳本。 可以將此計划任務設置為在事件上觸發。
請注意以下安全警告。 Powershell 5 中的腳本可以中斷,將控制權交給用戶。 對於 Powershell 6 及更高版本,此行為通過使用非交互選項禁用。
下面提出了兩種解決方案來解決原始問題。 兩者都使用中間程序從Session 0移動到Session 1 。
兩者都將 flash 簡要介紹為 PowerShell window ,這讓用戶感到不安並且難以隱藏。 下面的鏈接中提供了一些隱藏技巧。
如何在不顯示 Window 的情況下運行 PowerShell 腳本
鍵入的以下解決方案需要不帶空格的路徑。 如果給定,則必須使用完整路徑。 您將不得不編輯這些路徑以適應。
包括測試方法。
第一個解決方案需要PSExec.exe
程序。 它是以下鏈接中提供的PSTools
的一部分。 它還用於測試這兩種解決方案。
第二種解決方案需要ServiceUI.exe
程序。 它是Microsoft Deployment Toolkit (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)
WhoAmISession.ps1
whoami
$Session=(Get-Process -PID $pid).SessionID
echo "Session=$Session"
以Administrator
身份啟動cmd.exe
window 。
如鏡像所顯示,以下命令將提供系統用戶Session 0 PowerShell 執行環境。
E:\Programs\PSTools\psexec -s powershell.exe -file e:\test\WhoAmISession.ps1
如果在Session 0
中以SYSTEM
用戶身份運行,要在PowerShell
中顯示 Toast 通知,請使用以下命令。 如果當前活動的登錄用戶正在使用Session 1
,這將顯示 Toast 通知。 其他會話將需要一些修改。
E:\Programs\PSTools\psexec -s -i 1 C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file e:\test\BalloonTest.ps1
要測試以"Administrator"
身份啟動"cmd.exe"
window,然后輸入以下命令。 如果當前活動的登錄用戶正在使用Session 1
,這將顯示 Toast 通知,如圖所示。
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
如果在Session 0
中以SYSTEM
用戶身份運行,要在PowerShell
中顯示 Toast 通知,請使用以下命令。 這將向當前活動的登錄用戶顯示 Toast 通知。
E:\Programs\MDK\ServiceUI.exe C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file e:\test\BalloonTest.ps1
要測試以"Administrator"
身份啟動"cmd.exe"
window,然后輸入以下命令。 這將向當前活動的登錄用戶顯示 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
擴大接受的很好的答案:
當從SYSTEM
調用時,以下腳本可以以類似的方式用作上述答案中提到的psexec
和ServiceUI.exe
的替代品:
請注意,我沒有廣泛測試這些選項並且可能存在限制,例如 wrt executing user (如果不是SYSTEM
)或execution policies ,具體取決於您使用它們的上下文。不過我認為它們值得一提,因為它們可以是某些用例的好解決方案。
接受的答案提到了使用計划任務的可能性,但沒有對此進行擴展。
此解決方案具有以下優點(一些與其他解決方案共享):
SYSTEM
之外運行(例如,由具有管理權限的不同用戶運行) 這個想法是注冊一個將執行 PowerShell 的計划任務,告訴它運行一個吐司顯示腳本。 任務被注冊以便作為當前登錄的用戶運行,被手動和立即觸發(由腳本運行、未登錄的用戶——例如SYSTEM
),最后被刪除。
這是實現此目的的基本代碼,假設 toast 顯示邏輯包含在toast-showing-script.ps1
文件1中,例如,它需要一個ToastScriptParam
參數:
$LoggedInUser = Get-CimInstance –ClassName Win32_ComputerSystem | Select-Object -expand UserName
$TaskAction = New-ScheduledTaskAction -Execute “powershell.exe” -Argument "-NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File .\path\to\toast-showing-script.ps1 -ToastScriptParam ""$ToastContent""" # clearly, you will want to adapt the arguments to fit your use case
$TaskPrincipal = New-ScheduledTaskPrincipal -UserId $LoggedInUser
$Task = New-ScheduledTask -Action $TaskAction -Principal $TaskPrincipal
$ScheduledTask = $null
try {
$ScheduledTask = Register-ScheduledTask -TaskName 'TempToast' -TaskPath '\TempToast' -InputObject $Task
Start-ScheduledTask -InputObject $ScheduledTask
} finally {
if ($ScheduledTask) {
Unregister-ScheduledTask -InputObject $ScheduledTask -Confirm:$false
}
}
作為進一步的示例,您可以參考(或使用)我編寫的這個ToastNotification
PS 模塊,它就是這樣做的,但提供了更多選項。 它允許任何用戶簡單地調用Show-NotificationToLoggedInUser -Title "A title" -Message "Longer message"
來向當前登錄的用戶顯示 toast 通知。它是另一個不相關項目的一部分,但模塊本身可以用作支架-獨自的。
1當然,您也可以將此邏輯放在腳本塊中。 請記住,在計划任務的情況下, powershell.exe
不是“從另一個 PowerShell 主機運行”,因此您不能將ScriptBlock
傳遞給它,只能傳遞一個字符串。 有關詳細信息,請參閱有關-Command
選項的 Microsoft 文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.