PSExec for PowerShell
Today I ran into some issues calling PSExec.exe (https://technet.microsoft.com/en-us/sysinternals/bb897553 ) from PowerShell and realized that there is no native cmdlet to execute an application on a remote computer natively in PowerShell. After spending some time associated with encoding (psexec.exe expects UTF8, however PowerShell is sending Unicode) I decided to create a PowerShell script that could accomplish many of the tasks that PSExec could without needing a PSSession (to support down-level clients). Let me know what you think of Start-RemoteProcess:
#******************************************************************************
#* <Function Start-RemoteProcess> *
#* *
#* This function uses WMI to start a process on a remote computer. *
#* *
#* Input: *
#* [string] $Path - path to the file to execute *
#* [string] $Computer - computer to create the process on *
#* $Window { *
#* "Hidden" - hide the process window *
#* "Normal" - activate and display the window (default) *
#* "Minimized" - minimize the window *
#* "Maximized" - maximize the window *
#* } *
#* [string] $StartPath - the starting path for the application *
#* [string] $Title - set the title of the window *
#* [switch] $Priority { *
#* "Realtime" - set the process priority to realtime *
#* "High" - set the process priority to high *
#* "AboveNormal" - set the process priority to above normal *
#* "Normal" - set the process priority to normal (default) *
#* "BelowNormal" - set the process priority to below normal *
#* "Idle" - set the process priority to idle *
#* } *
#* [int] $X - set the x position of the window *
#* [int] $XSize - set the width of the window *
#* [int] $Y - set the y position of the window *
#* [int] $YSize - set the height of the window *
#* [PSCredential] $Credential - Credentials to connect to the computer *
#* [switch] $Elevate - Elevate the process in UAC *
#* *
#* Output: *
#* [wmiobject]"Win32_Process" - the process that was created *
#******************************************************************************
function Start-RemoteProcess {
param(
[Parameter(
Mandatory=$True,
ValueFromPipeline=$True,
HelpMessage='The process to start on the computer')]
[string] $Path,
[Parameter(
HelpMessage='The computer to start the process on')]
[string] $Computer = ".",
[Parameter(
HelpMessage='The starting working path for the application')]
[string] $StartPath = "c:\windows\system32\",
[ValidateSet("Hidden", "Normal", "Minimized", "Maximized",
IgnoreCase= $True)]
[Parameter(
HelpMessage='What state to start the program window')]
$Window = "Normal",
[Parameter(
HelpMessage='The title to assign to the window')]
[string] $Title,
[ValidateSet("RealTime", "High", "AboveNormal", "Normal",
"BelowNormal","Idle", IgnoreCase=$True)]
[Parameter(
HelpMessage='What priority to assign the new process')]
$Priority = "Normal",
[Parameter(
HelpMessage='The starting X position of the window')]
[int] $X,
[Parameter(
HelpMessage='The width of the window')]
[int] $XSize,
[Parameter(
HelpMessage='The starting Y position of the window')]
[int] $Y,
[Parameter(
HelpMessage='The starting height of the window')]
[int] $YSize,
[Parameter(
HelpMessage='Credentials to connect to the remote computer')]
[PSCredential] $Credential,
[Parameter(
HelpMessage='Elevate the process in User Account Control')]
[switch] $Elevate = $False
)
#Create a new instance of W32_ProcessStartup
$wmiProcessStartup = [wmiclass]"Win32_ProcessStartup"
#Set the window state for the process
switch($Window) {
"Hidden" {$wmiProcessStartup.Properties['ShowWindow'].Value = 0}
"Minimized" {$wmiProcessStartup.Properties['ShowWindow'].Value = 2}
"Maximized" {$wmiProcessStartup.Properties['ShowWindow'].Value = 3}
}
#Set the window title if specified
if ($Title -ne $Null) {$wmiProcessStartup.Properties['Title'].Value = $Title}
#Set the process priority, if specified
switch($Priority){
"RealTime" {$wmiProcessStartup.Properties['PriorityClass'].Value = 256}
"High" {$wmiProcessStartup.Properties['PriorityClass'].Value = 128}
"AboveNormal" {$wmiProcessStartup.Properties['PriorityClass'].Value = 32768}
"BelowNormal" {$wmiProcessStartup.Properties['PriorityClass'].Value = 16384}
"Idle" {$wmiProcessStartup.Properties['PriorityClass'].Value = 64}
}
#Set the window X position if specified
If ($X -ne $Null) {$wmiProcessStartup.Properties['X'].Value = $X}
#Set the window Y position if specified
If ($Y -ne $Null) {$wmiProcessStartup.Properties['Y'].Value = $Y}
#Set the window width if specified
If ($XSize -ne $Null) {$wmiProcessStartup.Properties['XSize'].Value = $XSize}
#Set the window height if specified
If ($YSize -ne $Null) {$wmiProcessStartup.Properties['YSize'].Value = $YSize}
if ($Credential -eq $Null) {
#Credentials were not specified
If ($Elevate) {
#Elevation was requested
return Invoke-WmiMethod -ComputerName $Computer -Class "Win32_Process" -Name Create -EnableAllPrivileges -ArgumentList $Path, $StartPath, $wmiProcessStartup
} else {
#Elevation was not requested
return Invoke-WmiMethod -ComputerName $Computer -Class "Win32_Process" -Name Create -ArgumentList $Path, $StartPath, $wmiProcessStartup
}
} else {
#Credentials were specified
If ($Elevate) {
#Elevation was requested
return Invoke-WmiMethod -ComputerName $Computer -Class "Win32_Process" -Name Create -EnableAllPrivileges -ArgumentList $Path, $StartPath, $wmiProcessStartup -Credential $Credential
} else {
#Elevation was not requested
return Invoke-WmiMethod -ComputerName $Computer -Class "Win32_Process" -Name Create -ArgumentList $Path, $StartPath, $wmiProcessStartup -Credential $Credential
}
}
}
#******************************************************************************
#* </Function Start-RemoteProcess> *
#******************************************************************************
Comments
Anonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
Have you managed to open a window for that process on a remote machine? When I say remote I mean other than $Computer = "." or $Computer="localhost".Anonymous
January 01, 2003
@Aleksandar Admittedly, I performed the remote call testing on remote computers but only performed the interactive applications on the computer I developed this on. I have found the parameters to add to the WIN32_ProcessStartup to choose which session to run in and will test this out and post the result if it works. Thanks for the diligence!Anonymous
March 30, 2014
It doesn't work. It just starts process WITHOUT elevated rights.