Powershell: Invoke-command doesn't always execute the commands entered in ScriptBlock

Created on 5 Mar 2019  路  3Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

PS C:\WINDOWS\system32> Invoke-Command -ComputerName server01 -ScriptBlock {calc.exe}

Expected behavior

The above command should open the calculator application on server01

Actual behavior

When the above command is executed multiple times, sometimes calculator application is opened correctly and sometimes it doesn't open at all.

Environment data

PSVersion                      5.1.17763.316
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17763.316
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Issue-Question Resolution-Answered

Most helpful comment

calc.exe is a GUI-based app and it shouldn't be open at all on the remote computer using the Invoke-Command.

All 3 comments

calc.exe is a GUI-based app and it shouldn't be open at all on the remote computer using the Invoke-Command.

The real reason is job control and calc.exe being a launcher.

If you Invoke-Command -ComputerName RemoteComputer -ScriptBlock { some-app.exe }, the remote computer will faithfully invoke some-app.exe. Let's try these:

$cn = Get-ComputerInfo -Property csname | select -expand csname
$cr = Get-Credential # Input the credential for the interactive user
Enable-PSRemoting -SkipNetworkProfileCheck

write-host 'before 1'
Invoke-Command -ComputerName $cn -Credential $cr -Command { calc; notepad; }
write-host 'after 1, before 2'
Invoke-Command -ComputerName $cn -Credential $cr -Command { start notepad -wait; }
write-host 'after 2, before 3'
Invoke-Command -ComputerName $cn -Credential $cr -Command { start calc -wait; }
write-host 'after 3'

# revert the settings
Disable-PSRemoting

What you will see is:

  1. Calculator opens or does not open.
  2. Notepad does not open.
  3. Console writes before 1.
  4. Console writes after 1, before 2.
  5. A black window opens, which is actually Notepad.
  6. After you close the black window, console writes after 2, before 3.
  7. Calculator opens (another window is opened if Calculator opened in step 1).
  8. Console writes after 3.

The reason:

  • Commands run remotely are not supposed to be interactive.
  • After finishing the command, any subprocesses are terminated because of job control.
  • calc.exe is not the app itself. It's a launcher for the WinRT version of Calculator. In command 1, it might successfully spawn the subprocess before it's terminated, or not. In command 3, it always succeeds because we waited for it. The real parent process of Calculator (Calculator.exe) is svchost.exe.
  • notepad.exe is the app itself. In command 1, it's terminated as soon as it's spawned, having no chance to display its GUI (or you might see a black window flickering). In command 2, its GUI glitches because of incorrect configuration.

Similarly, you could open microsoft-edge:https://bing.com/ with no problem, but you couldn't open mspaint.exe.

If you are sure your command is being sent to an interactive session with Explorer (which might be false), and you want to launch a program in the interactive session, you can ask Explorer to do it for you. Use the program found here. For example,

# shexp = ShellExecute from Explorer
# the second example elevates notepad.exe
Invoke-Command -ComputerName $cn -Credential $cr -Command {
start "$env:USERPROFILE\documents\playground\shexp.exe" -args 'notepad' -wait
start "$env:USERPROFILE\documents\playground\shexp.exe" -args 'notepad "" "" runas' -wait
}

This issue has been marked as answered and has not had any activity for 1 day. It has been closed for housekeeping purposes.

Was this page helpful?
0 / 5 - 0 ratings