PSExec and Powershell fails to run a program located in Program Files (x86)

I am struggling to use Psexec inside of a PS script to execute an interactive program. I have tried this:

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c "echo . | powershell notepad" 2> $null

... and it runs perfectly fine. Notepad is launched on a remote machine. Now, when I want to run .exe from Program Files (x86) I get absolutely nothing. I have tried this variations to run 1.exe located in ProgramFiles(x86):

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c "echo . | powershell "${env:ProgramFiles(x86)}\1.exe"" 2> $null

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c "echo . | powershell "${env:ProgramFiles(x86)}" + "\1.exe"" 2> $null

However none of them work. Any idea what´s wrong?

Answers


Try the following:

psexec cmd /c 'echo . | powershell "& \"${env:ProgramFiles(x86)}\1.exe\"' 2>$null

Note: To better focus on the fundamentals of the solution, I've simplified the psexec command, but the original command should work too.

  • The entire string passed to cmd /k is single-quoted to prevent PS from interpolating elements up front, notably ${env:ProgramFiles(x86)} whose expansion should be deferred until the command is executed on the target machine.

    • Note that you normally need a double-quoted string when you pass a command line to cmd /c when invoking from cmd.exe itself. From within PowerShell, however, this is not a requirement: PowerShell first parses the string - whether single- or double-quoted originally - interpolates, if applicable, and then passes the resulting string double-quoted to the external command.
  • Note the & \"...\" construct in the context of the powershell argument, which ensures that the path with embedded spaces is correctly executed.

    • Curiously, PS requires " chars. to be escaped as \" when a parameter is passed from the outside world (as opposed to escaping as `" inside the realm of PS).

    • The command passed to powershell as a whole must be double-quoted, because cmd.exe - in whose context powershell is invoked due to cmd /c - only recognizes double quotes as parameter delimiters and only double quotes protect the enclosed content (mostly) from interpretation.


Why your commands didn't work:

  • The primary problem was that the executable path that you wanted powershell.exe to invoke ended up containing spaces (C:\Program Files...), causing PowerShell not to recognize the entire path as a single argument. Such a path must be (a) quoted and (b) invoked with &, the call operator. (In the 2nd attempt, with + ... (string concatenation), you would have had to use & also, and enclose the concatenation in (...)).

    • For debugging, using cmd /k instead of cmd /c can give you a better sense of how the command is ultimately executed (/k keeps the console window open after execution of the command).
  • A subtler point is that by using a double-quoted string overall, ${env:ProgramFiles(x86)} was expanded on the source machine rather than on the target machine, where the definition of that environment variable may or may not be the same.


You're putting yourself in Escape Hell by mixing PowerShell, CMD and PsExec. If all you want is run an executable on a remote host, just stick with CMD and PsExec (run the command from CMD too):

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c echo. ^| "%ProgramFiles(x86)%\1.exe" 2>nul

That way you just need to escape the pipe (^|) and put the path with spaces in double quotes.


Need Your Help

Xcode 5.1 unused consts treated as error

c++ ios objective-c xcode

Since upgrading to Xcode 5.1 this morning, a C++ library I have included in my project is failing to build due to unused const.

How to modify a List<T> of structures in .NET?

.net list

Why I am not able to modify List items?