簡體   English   中英

如何以 SYSTEM 身份運行我的 PowerShell 模塊 cmdlet?

[英]How to run my PowerShell module cmdlet as SYSTEM?

創建了一個 PowerShell 模塊,它有一個 function 並為該 function 公開了一個 cmdlet。內置的 PowerShell 5.1 和 pwsh.exe 7.3.1(使用 MSI 安裝程序安裝)可以毫無問題地檢測和運行該 cmdlet。

現在我需要該 cmdlet 在 Windows 任務計划程序中“無論用戶是否登錄都運行”

當我嘗試以NT AUTHORITY\SYSTEM身份運行我的 PowerShell 模塊的 cmdlet 時,問題就出現了。

我需要這樣做,因為在任務計划程序中, 這似乎是獲得計划任務“無論用戶是否登錄都運行”的唯一方法。 (我不想手動輸入任何 Windows 用戶帳戶的用戶名或密碼)

在此處輸入圖像描述

理想情況下,我寧願使用內置的管理員安全組,但如您所見,如果用戶未登錄,我將無法運行該任務。

在此處輸入圖像描述

所以我真的被困在這里不知道該怎么辦。 我認為這是我遇到的邊緣情況之一。

我需要找到一種方法,以便當 PowerShell 作為 SYSTEM 運行時,它仍然能夠檢測到我的模塊的 cmdlet。

我知道當 PowerShell 作為 SYSTEM 運行時未檢測到我的 cmdlet,因為我使用PsExec64對其進行了測試。

我把我的 PowerShell 模塊放在這里(這是他們從在線畫廊默認安裝的地方):

C:\Users\<UserName>\OneDrive\Documents\PowerShell\Modules\ModuleFolder

這是我用來創建任務的 PowerShell 腳本的整個塊。

$action = New-ScheduledTaskAction -Execute "pwsh.exe" -Argument "-command 'myCmdLet -parameter1 $variable1"

# First thing I tried
$TaskPrincipal = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Administrators" -RunLevel Highest

# Second thing I tried
$TaskPrincipal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest

$trigger = New-ScheduledTaskTrigger -AtStartup

Register-ScheduledTask -Action $action -Trigger $trigger -Principal $TaskPrincipal -TaskName "Name" -Description "Description"

$TaskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Compatibility Win8 -StartWhenAvailable

Set-ScheduledTask -TaskName "Name" -Settings $TaskSettings 

更新:

找到了一種方法

$TaskPrincipal = New-ScheduledTaskPrincipal -LogonType S4U -UserId $env:USERNAME -RunLevel Highest

它以管理員身份運行任務(因為模塊 cmdlet 甚至在沒有管理員權限的情況下都無法工作)並且還檢查了我真正想做的這 2 個框。 但是,仍在尋找一種方法,使我的模塊的 cmdlet 在以 SYSTEM 身份運行時為 PowerShell 所知,它將提供 1 個好處,AFAIK,即消除對計算機上現有的特定用戶帳戶的依賴。

在此處輸入圖像描述

總結一下:

  • 您的問題是您希望計划任務使用的模塊安裝在當前用戶的 scope 中,而以不同用戶身份運行的任務(例如NT AUTORITY\SYSTEM )將不到。

    • 簡單的解決方案是通過傳遞給Install-Module-Scope AllUsers參數為所有用戶安裝模塊(需要提升)。

    • 但是,即使不可能或不需要,也有一個解決方案,即將完整的模塊路徑傳遞給在任務上下文中執行的顯式Import-Module調用,如下所示。

  • 由於您的任務需要以提升的方式運行,就像您 state 一樣,只有當該用戶是管理員時,才能在當前用戶的上下文中運行; 如您所見,您可以按如下方式進行設置(需要提升):

     $taskPrincipal = New-ScheduledTaskPrincipal -LogonType S4U -UserId $env:USERNAME -RunLevel Highest
  • 以用戶NT AUTORITY\SYSTEM身份運行任務總是會運行:

    • 考慮到此帳戶是具有廣泛本地權限的高權限內置帳戶,並且“充當.network 上的計算機”
    • 無形地(在服務運行的同一個隱藏 session / window 站中,因此使用-LogonType Service
    • 用戶當前是否登錄
    • 默認工作目錄為C:\Windows\System32
    • <hostname>$反映在$env:USERNAME中,其中<hostname>是本地計算機的名稱,以及C:\Windows\system32\config\systemprofile$HOME / $env:USERPROFILE文件夾。

以下自包含示例

  • 創建一個在創建后 5 秒執行一次的任務
  • 作為NT AUTHORITY\SYSTEM運行
  • 在當前用戶的主目錄中創建示例腳本模塊。 該任務顯式導入
  • 從該模塊調用 function,它報告有關運行時環境的信息並將結果記錄在當前用戶主目錄中的文本文件中。
  • 等待任務運行並顯示記錄的信息。
  • 自行清理(創建的臨時文件是~/_test.psm1~/_test.txt ,臨時任務名為_Test
#requires -RunAsAdministrator

$ErrorActionPreference = 'Stop'

try {

    # Create a simple script module that exports function Get-Foo,
    # in the current user's home dir., named '_test.psm1'
    @'
function Get-Foo { "Hi, I'm running at $(Get-Date)`n * as $env:USERNAME (whose home dir. is '$HOME')`n * in '$PWD'`n * $(('NON-elevated', 'ELEVATED')[[bool] (net session 2>$null)])." }
'@ > ~/_test.psm1

    # Set up the scheduled task:

    # The command (program) to run.
    # Import the test-module via its full path, call Get-Foo, and redirect all output streams
    # to file '_test.txt' in the current users' home dir.
    $action = New-ScheduledTaskAction -Execute powershell -Argument "-ExecutionPolicy Bypass -NoProfile -Command & { Import-Module `"$((Get-Item ~/_test.psm1).FullName)`"; Get-Foo } *> `"$((Get-Item ~).FullName)\_test.txt`""

    # Run as 'NT AUTHORITY\SYSTEM', which runs:
    #  * invisibly
    #  * whether or not someone is logged on
    #  * implicitly with elevation
    $user = New-ScheduledTaskPrincipal -UserID 'NT AUTHORITY\SYSTEM' -LogonType ServiceAccount

    # # Advanced settings such as whether to allow start on demand, not running when on batter power, ... 
    # $settings = New-ScheduledTaskSettingsSet

    # When to run it: Run a few seconds from now, once.
    $secsFromNow = 5
    $when = (Get-Date).AddSeconds($secsFromNow)
    $trigger = New-ScheduledTaskTrigger -Once -At $when

    # Create the task from the above.
    $newTask = New-ScheduledTask -Action $action -Principal $user -Trigger $trigger

    # Register the task with name '_Test'
    Write-Verbose -Verbose "Creating task..."
    Register-ScheduledTask '_Test' -InputObject $newTask -Force

    Write-Verbose -Verbose "Task will execute invisibly in $secsFromNow seconds, running as 'NT AUTHORITY\SYSTEM'. Waiting (plus a few extra seconds)..."
    Start-Sleep ($secsFromNow + 5) # Wait an extra few seconds to give the task time to complete.

    Write-Verbose -Verbose "Task is assumed to have run. Output logged:"
    Get-Content ~/_test.txt
}
finally {
    # Clean up.
    Remove-Item -ErrorAction Ignore ~/_test.psm1, ~/_test.txt
    Unregister-ScheduledTask -ErrorAction Ignore -TaskName _Test -Confirm:$false
}

樣本 output:

VERBOSE: Creating task...

TaskPath                                       TaskName                          State
--------                                       --------                          -----
\                                              _Test                             Ready
VERBOSE: Task will execute invisibly in 5 seconds, running as 'NT AUTHORITY\SYSTEM'. Waiting (plus a few extra seconds)...
VERBOSE: Task is assumed to have run. Output logged:
Hi, I'm running at 01/11/2023 17:06:04
 * as WORKSTATION1$ (whose home dir. is 'C:\Windows\system32\config\systemprofile')
 * in 'C:\Windows\system32'
 * ELEVATED.

最后 4 行是模塊函數的 ( Get-Foo的) output,證明模塊已成功導入到任務上下文中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM