Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions Invoke-CommandAs/Private/Invoke-ScheduledTask.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ function Invoke-ScheduledTask {
[Parameter(Mandatory = $false)][Switch]$AsSystem,
[Parameter(Mandatory = $false)][String]$AsInteractive,
[Parameter(Mandatory = $false)][String]$AsGMSA,
[Parameter(Mandatory = $false)][Switch]$RunElevated
[Parameter(Mandatory = $false)][Switch]$RunElevated,
[Parameter(Mandatory = $false)][Switch]$HideWindow

)

Expand Down Expand Up @@ -79,6 +80,14 @@ function Invoke-ScheduledTask {
Write-Verbose "$(Get-Date): ScheduledJob: Register"
$ScheduledJob = Register-ScheduledJob @JobParameters -ScriptBlock $JobScriptBlock -ArgumentList $JobArgumentList -ErrorAction Stop

$ExecPath = $ScheduledJob.PSExecutionPath
$ExecArgs = $ScheduledJob.PSExecutionArgs

if ($HideWindow) {
$ExecPath = "conhost.exe"
$ExecArgs = "--headless $($ScheduledJob.PSExecutionPath) $($ScheduledJob.PSExecutionArgs)"
}

If ($AsSystem -or $AsInteractive -or $AsUser -or $AsGMSA) {

# Use ScheduledTask to execute the ScheduledJob to execute with the desired credentials.
Expand All @@ -89,7 +98,7 @@ function Invoke-ScheduledTask {

Write-Verbose "$(Get-Date): ScheduledTask: Register"
$TaskParameters = @{ TaskName = $ScheduledJob.Name }
$TaskParameters['Action'] = New-ScheduledTaskAction -Execute $ScheduledJob.PSExecutionPath -Argument $ScheduledJob.PSExecutionArgs
$TaskParameters['Action'] = New-ScheduledTaskAction -Execute $ExecPath -Argument $ExecArgs
$TaskParameters['Settings'] = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
If ($AsSystem) {
$TaskParameters['Principal'] = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Expand Down Expand Up @@ -125,8 +134,8 @@ function Invoke-ScheduledTask {
$TaskDefinition = $ScheduleService.NewTask(0)
$TaskDefinition.Principal.RunLevel = $RunElevated.IsPresent
$TaskAction = $TaskDefinition.Actions.Create(0)
$TaskAction.Path = $ScheduledJob.PSExecutionPath
$TaskAction.Arguments = $ScheduledJob.PSExecutionArgs
$TaskAction.Path = $ExecPath
$TaskAction.Arguments = $ExecArgs

If ($AsUser) {
$Username = $AsUser.GetNetworkCredential().UserName
Expand Down
17 changes: 15 additions & 2 deletions Invoke-CommandAs/Public/Invoke-CommandAs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ function Invoke-CommandAs {

Type a user name, such as User01 or Domain01\User01. Or, enter a PSCredential object, such as one generated by the Get-Credential cmdlet. If you type a user name, this cmdlet prompts you for a password.


.PARAMETER HideWindow

ScheduledJob will be executed with the special hack to ensure that no window is shown when the task is executed.

This is done by using conhost.exe as the executable for the ScheduledTask, and passing the actual ScheduledJob as arguments to conhost.exe with the --headless flag.

#>

#Requires -Version 3
Expand Down Expand Up @@ -294,7 +301,11 @@ function Invoke-CommandAs {
[Parameter(Mandatory = $false)]
[Alias("Elevated")]
[switch]
${RunElevated}
${RunElevated},

[Parameter(Mandatory = $false)]
[switch]
${HideWindow}

)

Expand All @@ -304,7 +315,7 @@ function Invoke-CommandAs {

# Collect all the parameters, and prepare them to be splatted to the Invoke-Command
[hashtable]$CommandParameters = $PSBoundParameters
$ParameterNames = @('AsSystem', 'AsInteractive', 'AsUser', 'AsGMSA', 'RunElevated', 'FilePath','ScriptBlock', 'ArgumentList')
$ParameterNames = @('AsSystem', 'AsInteractive', 'AsUser', 'AsGMSA', 'RunElevated', 'HideWindow', 'FilePath','ScriptBlock', 'ArgumentList')
ForEach ($ParameterName in $ParameterNames) {
$CommandParameters.Remove($ParameterName)
}
Expand Down Expand Up @@ -366,6 +377,7 @@ function Invoke-CommandAs {
If ($Using:AsInteractive) { $Parameters['AsInteractive'] = $Using:AsInteractive }
If ($Using:AsGMSA) { $Parameters['AsGMSA'] = $Using:AsGMSA }
If ($Using:RunElevated) { $Parameters['RunElevated'] = $Using:RunElevated }
If ($Using:HideWindow) { $Parameters['HideWindow'] = $Using:HideWindow }
If ($Using:IsVerbose) { $Parameters['Verbose'] = $Using:IsVerbose }

Invoke-ScheduledTask @Parameters
Expand Down Expand Up @@ -394,6 +406,7 @@ function Invoke-CommandAs {
If ($AsInteractive) { $Parameters['AsInteractive'] = $AsInteractive }
If ($AsGMSA) { $Parameters['AsGMSA'] = $AsGMSA }
If ($RunElevated) { $Parameters['RunElevated'] = $RunElevated.IsPresent }
If ($HideWindow) { $Parameters['HideWindow'] = $HideWindow.IsPresent }
If ($IsVerbose) { $Parameters['Verbose'] = $IsVerbose }

Invoke-ScheduledTask @Parameters
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ Invoke-CommandAs -ScriptBlock { Get-Process } -AsUser $Credential
# Execute As Interactive session of another user.
Invoke-CommandAs -ScriptBlock { Get-Process } -AsInteractive 'username'

# Execute without showing a console window.
Invoke-CommandAs -ScriptBlock { Get-Process } -AsInteractive 'username' -HideWindow

```
### You can execute all the same commands as above against a remote machine.
### Use -ComputerName/Credential or -Session to authenticate
Expand Down