在PowerShell中,如何创建一个在启动时只运行1次然后自行删除的计划任务?

vatpfxk5  于 2023-06-23  发布在  Shell
关注(0)|答案(3)|浏览(285)

这是我目前收集到的。我需要一个预定的任务,只运行1次,在下一次启动(无论何时),它运行后,它应该删除自己。

Register-ScheduledTask -TaskName "Test 1" -InputObject (
    (
        New-ScheduledTask -Action (
            New-ScheduledTaskAction -Execute "PowerShell.exe"
        ) -Trigger (
            New-ScheduledTaskTrigger -Once -AtStartup # both of these can't be used
        ) -Settings (
            New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter 00:00:01 
        ) 
    ) | ForEach-Object { $_.Triggers[0].EndBoundary = <# 1 second after task is run #> ; $_ }
)

我不确定这是否可能,如果不可能,请让我知道,这样我就可以探索其他选择,但如果是这样,我需要帮助来弄清楚我如何才能实现它。EndBoundary看起来需要一个日期,但我没有任何给予它,因为它是未知的,当下一个启动。
我这样做是因为我需要在下一次启动时运行PowerShell代码(时间未知),并且只有1次。

tyu7yeag

tyu7yeag1#

-Once只适用于基于日历的触发器,例如“每月”、“每周”等。您不能将它与-AtStartup结合使用,这样它只能运行一次启动。
-DeleteExpiredTaskAfter只在有过期日期的情况下有效。但是到期日期在-AtStartup中并不适用,因为任务可能在机器引导之前到期。
执行后自行删除任务的一种简单方法是将删除添加到您无论如何都要执行的PowerShell脚本中。只需将以下行添加到PowerShell脚本:

Unregister-ScheduledTask -TaskName 'Test 1' -Confirm:$false

您也可以禁用它,这样它就不会再次运行,但您可以获得有关它何时运行以及结果的信息:

Disable-ScheduledTask -TaskName 'Test 1'

如果你不想修改你的主动作,你也可以添加第二个动作,它的定义如下:

New-ScheduledTaskAction -Execute powershell -Argument "-Command `"Unregister-ScheduledTask -TaskName 'Test 1' -Confirm:`$false`""

因此,总的来说,您的任务定义可能如下所示:

Register-ScheduledTask -TaskName "Test 1" -InputObject (
    (
        New-ScheduledTask -Action (
            (New-ScheduledTaskAction -Execute "PowerShell.exe"),
            (New-ScheduledTaskAction -Execute powershell -Argument "-ExecutionPolicy ByPass -Command `"Unregister-ScheduledTask -TaskName 'Test 1' -Confirm:`$false`"")
        ) -Trigger (
            New-ScheduledTaskTrigger -AtStartup
        )
    )
)
6ojccjat

6ojccjat2#

感谢mklement0评论这个问题,我找到了一种方法来实现我需要的,它不是使用计划任务,它使用这个:https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys
由于my module执行敏感任务,因此我需要一个完美的工作流程,以便即使发生停电等意外情况,代码完整性策略也会返回到强制模式。此审核/强制配置项策略交换仅持续几秒钟,但在此期间考虑意外事件非常重要。
在这里,我使用RunOnce设置了一个在计算机范围内的快照保证

################# Snap back guarantee #################
$registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
$command = @"
CiTool --update-policy "$((Get-Location).Path)\$PolicyID.cip" -json; Remove-Item -Path "$((Get-Location).Path)\$PolicyID.cip" -Force
"@
$command | Out-File "C:\EnforcedModeSnapBack.ps1"
New-ItemProperty -Path $registryPath -Name '*CIPolicySnapBack' -Value "powershell.exe -WindowStyle `"Hidden`" -ExecutionPolicy `"Bypass`" -Command `"& {&`"C:\EnforcedModeSnapBack.ps1`";Remove-Item -Path 'C:\EnforcedModeSnapBack.ps1' -Force}`"" -PropertyType String

然后执行一些模块相关的任务。
一旦模块成功地完成了任务并在强制模式下重新部署了CI策略,那么我将在finally块中删除snapback保证,因为不再需要它。

finally {                                          
    # Deploy Enforced mode CIP
    Write-Debug -Message "Finally Block Running"
    Update-BasePolicyToEnforced
    # Enforced Mode Snapback removal after base policy has already been successfully re-enforced
    Remove-Item -Path "C:\EnforcedModeSnapBack.ps1" -Force                     
    Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name "*CIPolicySnapBack" -Force
}

这样就不会在系统上留下任何痕迹,并且此功能可以透明地工作,当用户启动到安全模式时也可以工作。

vc6uscn9

vc6uscn93#

这是另一个答案,这个答案只使用计划任务。
正如我在第一个答案中所解释的,我这样做是为了保证CI策略强制模式Snapback。
首先,我创建一个计划任务

$taskAction = New-ScheduledTaskAction -Execute 'cmd.exe' -Argument '/c c:\cmd.cmd'
$taskTrigger = New-ScheduledTaskTrigger -AtLogOn
$principal = New-ScheduledTaskPrincipal -GroupId 'BUILTIN\Administrators' -RunLevel Highest
$TaskSettings = New-ScheduledTaskSettingsSet -Hidden -Compatibility Win8 -DontStopIfGoingOnBatteries -Priority 0 -AllowStartIfOnBatteries
Register-ScheduledTask -TaskName 'EnforcedModeSnapBack' -Action $taskAction -Trigger $taskTrigger -Principal $principal -Settings $TaskSettings
                                
Set-Content "c:\cmd.cmd" -Value @"
CiTool --update-policy "$((Get-Location).Path)\$PolicyID.cip" -json
schtasks /Delete /TN EnforcedModeSnapBack /F
del "%~f0"
"@

然后我做一些模块相关的任务
然后有最后块运行,如果一切都成功完成

Unregister-ScheduledTask -TaskName 'EnforcedModeSnapBack' -Confirm:$false
Remove-Item -Path 'c:\cmd.cmd' -Force

此方法还会删除其自身以及创建的任务,因此不会留下任何痕迹。
P.S -AtLogOn在这里很重要,-AtStartup不会与此方法一起工作。
https://learn.microsoft.com/en-us/powershell/module/scheduledtasks/new-scheduledtasksettingsset

相关问题