이 샘플 스크립트를 복사하여 붙여넣고 환경에 필요한 대로 수정합니다.
<# . 시놉시스 보안 부팅 업데이트 예약된 작업을 사용하도록 설정합니다.
.DESCRIPTION 이 스크립트는 Windows 보안 부팅 업데이트 예약된 작업을 보장합니다. (\Microsoft\Windows\PI\Secure-Boot-Update)가 사용하도록 설정되어 있습니다. 사용하지 않도록 설정된 경우 사용할 수 있습니다. 작업이 삭제된 경우 다시 만들 수 있습니다.
.PARAMETER Action 수행할 작업입니다. 유효한 값: 검사, 사용, 만들기 - 검사: 작업 상태 검사 - 사용: (기본값) 사용하지 않도록 설정된 경우 작업을 사용하도록 설정합니다. 작업이 누락된 경우 만들라는 메시지가 표시됩니다.- 만들기: 작업이 없는 경우 만들기
.PARAMETER ComputerName 선택적. 작업을 검사/사용하도록 설정할 컴퓨터 이름 배열입니다.지정하지 않으면 로컬 컴퓨터에서 실행됩니다.
.PARAMETER Credential 선택적. 원격 컴퓨터 액세스를 위한 자격 증명입니다.
.PARAMETER Quiet 프롬프트를 표시하지 않으며 자동으로 예에 응답합니다. 자동화에 유용합니다.
.EXAMPLE .\Enable-SecureBootTask.ps1 # 로컬 컴퓨터에서 작업 상태 사용하도록 설정
.EXAMPLE .\Check-SecureBootScheduledTask.ps1 사용 # 사용하지 않도록 설정된 경우 작업을 사용하도록 설정합니다. 누락된 경우 만들 프롬프트.
.EXAMPLE .\Check-SecureBootScheduledTask.ps1 만들기 # 삭제된 경우 작업을 만든 다음 해당 상태 확인합니다.
.EXAMPLE .\Check-SecureBootScheduledTask.ps1 검사 -ComputerName "PC1", "PC2" # 원격 머신에서 작업을 확인합니다.
.NOTES 작업을 사용하거나 만들려면 관리자 권한이 필요합니다.작업 경로: \Microsoft\Windows\PI\Secure-Boot-Update 작업은 상승된 권한으로 12시간마다 taskhostw.exe 실행됩니다.#>
[CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position=0)] [ValidateSet('검사', 'enable', 'create', '')] [string]$Action = 'enable',
[Parameter()] [string[]]$ComputerName,
[Parameter()] [PSCredential]$Credential,
[Parameter()] [별칭('Force', 'Silent')] [switch]$Quiet )
# Convert Action to switches for backward compatibility $Enable = $Action -eq 'enable' $Create = $Action -eq 'create'
# Download URL: https://aka.ms/getsecureboot -> "Deployment and Monitoring Samples" # 참고: 이 스크립트는 보안 부팅 업데이트 작업을 사용하도록 설정하기 위해 엔드포인트에서 실행됩니다.
$TaskPath = "\Microsoft\Windows\PI\" $TaskName = "Secure-Boot-Update"
function Get-SecureBootTaskStatus { [CmdletBinding()] param( [string]$Computer = $env:COMPUTERNAME )
$result = [PSCustomObject]@{ ComputerName = $Computer TaskExists = $false TaskState = $null IsEnabled = $false LastRunTime = $null NextRunTime = $null 오류 = $null }
try { if ($Computer -eq $env:COMPUTERNAME -또는 $Computer -eq "localhost" -또는 $Computer -eq ".") { # 더 안정적인 작업 검색을 위해 schtasks.exe 사용 $schtasksOutput = schtasks.exe /Query /TN "$TaskPath$TaskName" /FO CSV 2>&1 if ($LASTEXITCODE -ne 0) { # 작업을 찾을 수 없음은 오류가 아닙니다. 즉, 작업이 존재하지 않음을 의미합니다. $result. TaskExists = $false return $result } # CSV 출력 구문 분석 $taskData = $schtasksOutput | ConvertFrom-Csv if ($taskData) { $result. TaskExists = $true $result. TaskState = $taskData.Status $result. IsEnabled = ($taskData.Status -eq 'Ready' -또는 $taskData.Status -eq 'Running') # 데이터에서 다음 런타임 가져오기 시도 if ($taskData.'Next Run Time' -and $taskData.'Next Run Time' -ne 'N/A') { try { $result. NextRunTime = [DateTime]::P arse($taskData.'다음 런타임') } catch { } } } } else { # 원격 컴퓨터 - schtasks에서 Invoke-Command 사용 $remoteResult = Invoke-Command -ComputerName $Computer -ScriptBlock { param($fullTaskName) $output = schtasks.exe /Query /TN $fullTaskName /FO CSV 2>&1 @{ ExitCode = $LASTEXITCODE 출력 = $output } } -ArgumentList "$TaskPath$TaskName" -ErrorAction Stop
if ($remoteResult.ExitCode -ne 0) { # 작업을 찾을 수 없음은 오류가 아닙니다. 즉, 작업이 존재하지 않음을 의미합니다. $result. TaskExists = $false return $result }
$taskData = $remoteResult.Output | ConvertFrom-Csv if ($taskData) { $result. TaskExists = $true $result. TaskState = $taskData.Status $result. IsEnabled = ($taskData.Status -eq 'Ready' -또는 $taskData.Status -eq 'Running') } } } catch { $result. 오류 = $_. Exception.Message }
return $result }
function New-SecureBootTask { [CmdletBinding(SupportsShouldProcess)] param( [string]$Computer = $env:COMPUTERNAME )
$success = $false $errorMsg = $null
# Task definition - matches the original Windows Secure Boot Update task # SBServicing 클래스에서 ComHandler 사용, LocalSystem으로 실행 $taskXml = @" <?xml version="1.0" encoding="UTF-16"?> <작업 버전="1.6" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <날짜>2012-02-07T16:39:20</Date> <SecurityDescriptor>O:BAG:BAD:P(A;; Fa;;; BA)(A;; Fa;;; SY)(A;; FRFX;;; LS)</SecurityDescriptor> <원본>'$(@%SystemRoot%\system32\TpmTasks.dll,-601)</Source> <작성자>'$(@%SystemRoot%\system32\TpmTasks.dll,-600)</Author> <설명>'$(@%SystemRoot%\system32\TpmTasks.dll,-604)</Description> <URI>\Microsoft\Windows\PI\Secure-Boot-Update</URI> </RegistrationInfo> <보안 주체> <보안 주체 id="LocalSystem"> <UserId>S-1-5-18</UserId> </Principal> </Principals> <설정> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> ><0 StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> ><4 ExecutionTimeLimit>PT1H</ExecutionTimeLimit> ><8 MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <StartWhenAvailable>true</StartWhenAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine> </설정> 트리거>< <BootTrigger> <지연>PT5M</delay> <반복> <간격>PT12H</interval> </반복> </BootTrigger> </트리거> <Actions Context="LocalSystem"> <ComHandler> <ClassId>{5014B7C8-934E-4262-9816-887FA745A6C4}</ClassId> 데이터>< <! [CDATA[SBServicing]]></Data> </ComHandler> </Actions> </Task> " @
try { if ($Computer -eq $env:COMPUTERNAME -또는 $Computer -eq "localhost" -또는 $Computer -eq ".") { if ($PSCmdlet.ShouldProcess("$TaskPath$TaskName", "예약된 작업 만들기")) { # XML을 임시 파일에 저장하고 가져오기 $tempFile = [System.IO.Path]::GetTempFileName() $taskXml | Out-File -FilePath $tempFile -인코딩 유니코드 -Force $output = schtasks.exe /Create /TN "$TaskPath$TaskName" /XML $tempFile /F 2>&1 Remove-Item $tempFile -Force -ErrorAction SilentlyContinue if ($LASTEXITCODE -eq 0) { $success = $true } else { $errorMsg = $output -join " " } } } else { if ($PSCmdlet.ShouldProcess("$Computer\$TaskPath$TaskName", "예약된 작업 만들기")) { $result = Invoke-Command -ComputerName $Computer -ScriptBlock { param($taskPath, $taskName, $xml) $tempFile = [System.IO.Path]::GetTempFileName() $xml | Out-File -FilePath $tempFile -유니코드 인코딩 -Force $output = schtasks.exe /Create /TN "$taskPath$taskName" /XML $tempFile /F 2>&1 Remove-Item $tempFile -Force -ErrorAction SilentlyContinue @{ ExitCode = $LASTEXITCODE; 출력 = $output } } -ArgumentList $TaskPath, $TaskName, $taskXml -ErrorAction Stop if($result. ExitCode -eq 0) { $success = $true } else { $errorMsg = $result. 출력 -join " " } } } } catch { $errorMsg = $_. Exception.Message }
return @{ 성공 = $success 오류 = $errorMsg } }
function Enable-SecureBootTask { [CmdletBinding(SupportsShouldProcess)] param( [string]$Computer = $env:COMPUTERNAME )
$success = $false $errorMsg = $null
try { if ($Computer -eq $env:COMPUTERNAME -또는 $Computer -eq "localhost" -또는 $Computer -eq ".") { if ($PSCmdlet.ShouldProcess("$TaskPath$TaskName", "예약된 작업 사용")) { $output = schtasks.exe /Change /TN "$TaskPath$TaskName" /ENABLE 2>&1 if ($LASTEXITCODE -eq 0) { $success = $true } else { $errorMsg = $output -join " " } } } else { if ($PSCmdlet.ShouldProcess("$Computer\$TaskPath$TaskName", "예약된 작업 사용")) { $result = Invoke-Command -ComputerName $Computer -ScriptBlock { param($fullTaskName) $output = schtasks.exe /Change /TN $fullTaskName /ENABLE 2>&1 @{ ExitCode = $LASTEXITCODE; 출력 = $output } } -ArgumentList "$TaskPath$TaskName" -ErrorAction Stop if($result. ExitCode -eq 0) { $success = $true } else { $errorMsg = $result. 출력 -join " " } } } } catch { $errorMsg = $_. Exception.Message }
return @{ 성공 = $success 오류 = $errorMsg } }
# Main execution Write-Host "" Write-Host "========================================" -ForegroundColor Cyan Write-Host "보안 부팅 업데이트 작업 사용" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" Write-Host "작업: $TaskPath$TaskName" -ForegroundColor Gray Write-Host ""
# Determine target computers $targets = if ($ComputerName) { $ComputerName } else { @($env:COMPUTERNAME) }
$results = @()
foreach ($computer in $targets) { Write-Host "확인: $computer" -ForegroundColor 노란색 $상태 = Get-SecureBootTaskStatus -Computer $computer if ($상태. 오류) { Write-Host " 오류: $($상태. 오류)" -ForegroundColor Red } elseif (-not $상태. TaskExists) { Write-Host "이 시스템에 작업이 없습니다." -ForegroundColor Red # 요청된 경우 만들기 또는 사용이 지정된 경우 프롬프트 $shouldCreate = $Create if (-not $shouldCreate -and $Enable) { Write-Host "" Write-Host "작업이 삭제되었을 수 있습니다." -ForegroundColor 노란색 if ($Quiet) { Write-Host " 자동 만들기 작업(자동 모드)" -ForegroundColor Cyan $shouldCreate = $true } else { $confirm = Read-Host " 작업을 다시 만들겠습니까? (Y/N)" if ($confirm -eq 'Y' -또는 $confirm -eq 'y') { $shouldCreate = $true } } } if ($shouldCreate) { Write-Host "작업 만들기..." -ForegroundColor 노란색 $createResult = New-SecureBootTask -Computer $computer if ($createResult.Success) { Write-Host "작업이 성공적으로 생성되었습니다." -ForegroundColor 녹색 # 다시 검사 상태 $상태 = Get-SecureBootTaskStatus -Computer $computer if ($상태. TaskExists) { $stateColor = if ($상태. IsEnabled) { "Green" } else { "Red" } Write-Host " 상태: $($상태. TaskState)" -ForegroundColor $stateColor } } else { Write-Host "만들지 못했습니다: $($createResult.Error)" -ForegroundColor Red } } } else { $stateColor = if ($상태. IsEnabled) { "Green" } else { "Red" } Write-Host " 상태: $($상태. TaskState)" -ForegroundColor $stateColor if ($상태. LastRunTime -및 $상태. LastRunTime -ne [DateTime]::MinValue) { Write-Host " 마지막 실행: $($상태. LastRunTime)" -ForegroundColor Gray } if ($상태. NextRunTime -및 $상태. NextRunTime -ne [DateTime]::MinValue) { Write-Host " 다음 실행: $($상태. NextRunTime)" -ForegroundColor Gray }
# Enable if requested and currently disabled if ($Enable -and -not $상태. IsEnabled) { Write-Host "작업 사용..." -ForegroundColor 노란색 $enableResult = Enable-SecureBootTask -Computer $computer if ($enableResult.Success) { Write-Host "작업이 성공적으로 사용됨" -ForegroundColor 녹색 # 다시 검사 상태 $상태 = Get-SecureBootTaskStatus -Computer $computer } else { Write-Host "사용하도록 설정하지 못했습니다. $($enableResult.Error)" -ForegroundColor Red } } elseif($Enable 및 $상태. IsEnabled) { Write-Host "작업이 이미 사용됨" -ForegroundColor 녹색 } } $results += $상태 Write-Host "" }
# Summary Write-Host "========================================" -ForegroundColor Cyan Write-Host " 요약" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan
$enabled = ($results | Where-Object { $_.IsEnabled }).Count $disabled = ($results | Where-Object { $_. TaskExists -and -not $_. IsEnabled }). 횟수 $notFound = ($results | Where-Object { -not $_. TaskExists }). 횟수 $errors = ($results | Where-Object { $_. 오류 }). 횟수
Write-Host "Total Checked: $($results.Count)" Write-Host "사용: $enabled" -ForegroundColor 녹색 if ($disabled -gt 0) { Write-Host "Disabled: $disabled" -ForegroundColor Red } if ($notFound -gt 0) { Write-Host "찾을 수 없음: $notFound" -ForegroundColor Yellow } if ($errors -gt 0) { Write-Host "Errors: $errors" -ForegroundColor Red }
# Return results for pipeline $results