Powershell – psexec hangs only when using username and password and calling from a PowerShell script

powershellpstools

I am attempting to use psexec to start a process in an interactive session that has already been opened. Both my machine and the remote machine are Windows 7. Using the command from within command prompt works fine, the executable is started and is visible in the GUI.

psexec64 -accepteula -nobanner \\hostname -u domain\user -p password -h -i 2 -d C:\workingdir\subfolder\application.exe

However, when I attempt to execute the same call within a PowerShell script, it does not work. See the full script for context.

# invalid args: $psExecArgs = "-accepteula", "-nobanner", "-u domain`\${username}", "-p ${password}", "-h", "-i ${sessionId}", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
# hangs: $psExecArgs = "-accepteula", "-nobanner", "-u domain`\${username}", "-p ${password}", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
$psExecArgs = "-accepteula", "-nobanner", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
& $EchoArgsPath $psExecArgs
$result = & $PsExecPath $psExecArgs #2>$null
  • When giving all of the same arguments, the value of $result is the psexec help as if an invalid argument is given.
  • When -i 2 is removed, psexec shows in the running processes list on my machine and appears to hang; no psexecsvc process is started on the remote machine.
  • When -u and -p are removed, psexec is started but as expected, the process starts in a non-interactive session on my account on the remote machine.

I see the same kind of behavior when using pslist and pskill so I replaced those with tasklist and taskkill. I have ensured that UAC is disabled and that I can map to the Admin$ share on the remote machine using the credentials I am providing.

While typing this question I found a question suggesting that stdin might be an issue but I'm not sure if it is relevant in my case.

Best Answer

Declaring a variable like $psExecArgs = "-accepteula", "-nobanner" makes an array of strings.

You are running whatever the strings say (using &) instead of launching a process and providing arguments, so the arguments would need to be simple strings as well (not an array of strings).

Then to further muddy it, if you were to provide the arguments in a single string ($psExecArgs = "-accepteula -nobanner"), that actually only appears as one argument to PSExec, and won't work either.

So, instead of trying to run the strings, one option is to use PowerShell's Start-Process command, which expects the arguments to be fed to it in an array (as you are currently doing).

Try changing command lines like:

& $PsExecPath $psExecArgs

to something like:

Start-Process $PsExecPath $psExecArgs

You'll have to handle the return code and errors a little differently, something like:

try {
  $process = (Start-Process -FilePath $psexec -ArgumentList $psExecArgs -NoNewWindow -PassThru)
} 
catch {
  Write-Output "Error launching process!" 
  Write-Output $_.Exception.Message
  $process = $null
}
finally {
  if ($process) {
    $process.WaitForExit()
    Write-Host "Process exit code: " $process.ExitCode
  }
}