Mike Melone's Blog

A deep-dive on PKI, information security, and the Windows platform

PSExec for PowerShell

PSExec for PowerShell

  • Comments 4
  • Likes

Today I ran into some issues calling PSExec.exe (http://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
  • 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".

  • @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!

  • @Aleksandar I believe the issue is due to the Windows Management Instrumentation (WMI) service not having the ability to interact with the desktop (the check box under the "Log On" tab).  I am going to try to launch the application in a different manner and will post results.

  • It doesn't work. It just starts process WITHOUT elevated rights.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment