如何以SYSTEM身份运行PowerShell模块cmdlet?

yyyllmsg  于 2023-02-04  发布在  Shell
关注(0)|答案(1)|浏览(173)

创建了PowerShell模块,它具有函数并为该函数公开cmdlet。内置PowerShell 5.1和pwsh.exe 7.3.1(使用MSI安装程序安装)可以检测并运行cmdlet,没有问题。
现在,我需要该cmdlet在Windows任务计划程序中**"无论用户是否登录都运行"**。
当我尝试将PowerShell模块的cmdlet作为NT AUTHORITY\SYSTEM运行时,问题出现了。
我需要这样做,因为在任务调度程序中,that appears to be是获得调度任务"无论用户是否登录都运行"的唯一方法。(我不想手动输入任何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在没有管理员权限的情况下甚至无法工作),并且还选中了这两个框,这是我非常想做的。但是,仍然在寻找一种方法,使PowerShell在以SYSTEM身份运行时知道我的模块cmdlet,它将提供1个好处,即AFAIK,这是为了消除对计算机上现有特定用户帐户的依赖性。

bqjvbblv

bqjvbblv1#

总结如下:

  • 您的问题是,您希望计划任务使用的模块安装在 * 当前用户 * 的范围内,而以 * 不同 * 用户身份运行的任务(如NT AUTORITY\SYSTEM)将 * 看不到 * 该模块。
  • 最简单的解决方案是通过将-Scope AllUsers参数传递给Install-Module(需要提升),为 * 所有 * 用户安装该模块。
  • 然而,即使这是"不"可能或不希望的,也有一个解决方案,即将"完整模块路径"传递给在任务上下文中执行的显式Import-Module调用,如下所示。
  • 由于您的任务需要在提升的情况下运行,如您所述,只有当用户是管理员时,才可以选择在 * current * 用户的上下文中运行;正如您所发现的,您可以按如下方式进行设置(需要高程):
$taskPrincipal = 
  New-ScheduledTaskPrincipal -LogonType S4U -UserId $env:USERNAME -RunLevel Highest
  • 以用户NT AUTORITY\SYSTEM的身份运行任务 * 总是 * 运行:
  • 假定该帐户是具有广泛的 * 本地 * 特权的高特权内置帐户,并且其"充当网络上的计算机",则使用提升。
  • 不可见地(在服务运行的同一隐藏会话/窗口站中,因此使用-LogonType Service
  • 用户当前是否已登录
  • 默认情况下C:\Windows\System32为工作控制器
  • <hostname>$反映在$env:USERNAME中,其中<hostname>是本地计算机的名称,以及C:\Windows\system32\config\systemprofile$HOME/$env:USERPROFILE文件夹。

以下自包含示例

  • 创建任务,该任务在创建后5秒执行 * 一次 *
  • NT AUTHORITY\SYSTEM运行
  • 在当前用户的主目录中创建任务明确导入的示例脚本模块
  • 从该模块调用函数,该函数报告有关运行时环境的信息,并将结果记录在当前用户主目录的文本文件中。
  • 等待任务运行并显示记录的信息。
  • 清除后自己(创建的临时文件为~/_test.psm1~/_test.txt,临时任务命名为_Test
#requires -RunAsAdministrator

# Abort on any error.
# Note: Since the *-ScheduledTask* cmdlets are implemented as 
#       CDXML-based *script* modules, they only see preference vars.
#       in the *global* scope - see https://github.com/PowerShell/PowerShell/issues/4568
$prevEaPref = $global:ErrorActionPreference
$global: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
    $global:ErrorActionPreference = $prevEaPref
}

样本输出:

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)的输出,证明模块已成功导入到任务上下文中。

相关问题