繁体   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