The proper way to Action a PowerShell script is to either convert it to a ONE LINER, or simply Encode the contents. In this example, I want to create a Scheduled Task with the following results
Export third party drivers to C:\Exported Drivers
Log to C:\Windows\Logs\Drivers
Run as SYSTEM for Standard Users
Action Script
The following script is what would be run to export the drivers to C:\ExportedDrivers and to write a Transcript to C:\Windows\Logs\Drivers
Copy $TaskName = 'Export-WindowsDriverOnline'
#======================================================================================
# Logs
#======================================================================================
$TaskLogs = "$env:SystemRoot\Logs\Drivers"
if (!(Test-Path $TaskLogs)) {New-Item $TaskLogs -ItemType Directory -Force | Out-Null}
$TaskLogName = "$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-$TaskName.log"
Start-Transcript -Path (Join-Path $TaskLogs $TaskLogName)
#======================================================================================
# Main
#======================================================================================
#if (!(Test-Path $TaskLogs)) {New-Item $TaskLogs -ItemType Directory -Force | Out-Null}
Export-WindowsDriver -Online -Destination $env:SystemDrive\ExportedDrivers
#======================================================================================
# Complete
#======================================================================================
Stop-Transcript
Encoding the Command
Its easy enough to put the script into a Variable $TaskScript
and convert the Variable to $EncodedCommand
Copy #======================================================================================
# Script
$TaskScript = @'
$TaskName = 'Export-WindowsDriverOnline'
#======================================================================================
# Logs
#======================================================================================
$TaskLogs = "$env:SystemRoot\Logs\Drivers"
if (!(Test-Path $TaskLogs)) {New-Item $TaskLogs -ItemType Directory -Force | Out-Null}
$TaskLogName = "$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-$TaskName.log"
Start-Transcript -Path (Join-Path $TaskLogs $TaskLogName)
#======================================================================================
# Main
#======================================================================================
#if (!(Test-Path $TaskLogs)) {New-Item $TaskLogs -ItemType Directory -Force | Out-Null}
Export-WindowsDriver -Online -Destination $env:SystemDrive\ExportedDrivers
#======================================================================================
# Complete
#======================================================================================
Stop-Transcript
'@
#======================================================================================
# Encode the Script
$EncodedCommand = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($TaskScript))
Splat the Action
The following example is how to Action the $EncodedCommand
in the Scheduled Task
Copy $Action = @{
Execute = 'powershell.exe'
Argument = "-ExecutionPolicy ByPass -EncodedCommand $EncodedCommand"
}
Full Script
Once I have that information, I can complete the script for creating my Scheduled Task
Copy #======================================================================================
# Task Properties
$TaskName = 'Export-WindowsDriverOnline'
$TaskPath = '\Corporate\Drivers'
$Description = @"
Exports third party drivers to $env:SystemDrive\ExportedDrivers
Transcripts are stored in $env:SystemRoot\Logs\Drivers
Runs as SYSTEM and does not display any progress or results
PowerShell Encoded Script
Version 21.1.19
"@
#======================================================================================
# Script
$TaskScript = @'
$TaskName = 'Export-WindowsDriverOnline'
#======================================================================================
# Logs
#======================================================================================
$TaskLogs = "$env:SystemRoot\Logs\Drivers"
if (!(Test-Path $TaskLogs)) {New-Item $TaskLogs -ItemType Directory -Force | Out-Null}
$TaskLogName = "$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-$TaskName.log"
Start-Transcript -Path (Join-Path $TaskLogs $TaskLogName)
#======================================================================================
# Main
#======================================================================================
#if (!(Test-Path $TaskLogs)) {New-Item $TaskLogs -ItemType Directory -Force | Out-Null}
Export-WindowsDriver -Online -Destination $env:SystemDrive\ExportedDrivers
#======================================================================================
# Complete
#======================================================================================
Stop-Transcript
'@
#======================================================================================
# Encode the Script
$EncodedCommand = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($TaskScript))
#======================================================================================
# Splat the Task
$Action = @{
Execute = 'powershell.exe'
Argument = "-ExecutionPolicy ByPass -EncodedCommand $EncodedCommand"
}
$Principal = @{
UserId = 'SYSTEM'
RunLevel = 'Highest'
}
$Settings = @{
AllowStartIfOnBatteries = $true
Compatibility = 'Win8'
MultipleInstances = 'Parallel'
ExecutionTimeLimit = (New-TimeSpan -Minutes 60)
}
$ScheduledTask = @{
Action = New-ScheduledTaskAction @Action
Principal = New-ScheduledTaskPrincipal @Principal
Settings = New-ScheduledTaskSettingsSet @Settings
Description = $Description
}
#======================================================================================
# Build the Task
New-ScheduledTask @ScheduledTask | Register-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Force
#======================================================================================
# Apply Authenticated User Permissions
$Scheduler = New-Object -ComObject "Schedule.Service"
$Scheduler.Connect()
$GetTask = $Scheduler.GetFolder($TaskPath).GetTask($TaskName)
$GetSecurityDescriptor = $GetTask.GetSecurityDescriptor(0xF)
if ($GetSecurityDescriptor -notmatch 'A;;0x1200a9;;;AU') {
$GetSecurityDescriptor = $GetSecurityDescriptor + '(A;;GRGX;;;AU)'
$GetTask.SetSecurityDescriptor($GetSecurityDescriptor, 0)
}
Results
The Task gets created properly with the Encoded script
Running the Task works flawlessly in exporting the drivers
And everything is logged in the PowerShell Transcript, including the Encoded Script