Search code examples
powershellcommand-line

Powershell - Passing commands to spawned Command Prompt


I'll try to explain the use case here. I am writing a script to automate the management of remote services. This can easily be done with sc.exe via command prompt. However, this use case is to write the script via Powershell.

I currently have the following:

Start-Process cmd.exe -ArgumentList "/c runas.exe /netonly /user:$username cmd.exe"

The $username variable has already been set, and is in the domain\username format. The above works. It pops up a cmd window prompting to enter the password (it'd be awesome if the full credential could be passed via Get-Credential, including the password, but I understand the security implications there). Once the password is entered and you press Enter, a new command prompt window opens, running as the given user. It is in this new window where we want to run:

 sc.exe \\$target query

Again, the $target variable is already set. However, the goal here is not to have the user manually run that command. The hope was to pass that command through the initial Start-Process command in the hopes that the only manual user action would be the act of typing the password.

I've not had a ton of luck on the feasibility of this. Is it possible? The end goal would hopefully be to pass the sc.exe command, and take action on the output (were services returned? great, now do "this"...)


Solution

    • You don't need cmd.exe to invoke runas.exe - just invoke the latter directly.

    • Since runas.exe launches the target program asynchronously you don't strictly need Start-Process either - unless you want to wait for the runas.exe-launched target program to exit.

    • If you want to launch a cmd.exe process as a different user with a command, use the latter's /C or /K option, followed by a single-line command line; /C executes the command line and then exits (thereby closing the window), whereas /K keeps the cmd.exe enters an interactive session after execution of the command line (thereby keeping the window open).

    Therefore, use something like the following to asynchronously start a cmd.exe process as a given user, execute the specified command and enter an interactive session:

    runas.exe /netonly /user:$username "cmd.exe /K sc.exe \\$target query"
    

    If you want to wait for the cmd.exe process to exit and make it do so right after executing the specified command, use Start-Process -Wait and cmd.exe's /C option; however, note that in order to examine the results you then need to redirect cmd.exe's output to a file; e.g.:

    # Note the use of /C rather than /K and
    # >out.txt 2>&1 to capture both stdout and stderr output in file "out.txt"
    Start-Process -Wait runas.exe "/netonly /user:$username `"cmd.exe /C sc.exe \\$target query >out.txt 2>&1`""
    
    # Now you can examine file "out.txt" for the results.