5

I have another command line program which I invoke from my powershell script and would like to run some interactive commands in that window once it is opened from power shell.

In other words - I do a Invoke-Item $link_to_app which opens up the interactive command line for that application and now I would like to use the application specific commands from within powershell scripts.

e.g. app.exe -help to invoke the help command of the app.exe.

Any pointers would help. Thanks!

Eduardo M
  • 1,007
  • 11
  • 17
user1575430
  • 51
  • 1
  • 1
  • 2

2 Answers2

2

Try this:

$app = 'app.exe -help'
Invoke-Expression $app

Tested with this and it worked as expected:

$pingTest = 'ping -n 8 127.0.0.1'
Invoke-Expression $pingTest

From your expanded explanation you appear to want to run 2 commands within the same command prompt. This is possible, however, I'm not sure it will work in your scenario. For example:

test1.bat: echo "hello!"

test2.bat: echo "goodbye!"

$batchTest = "test1.bat && test2.bat"
cmd /c $batchTest 

output:

D:\Test>echo "hello!"
"hello!"

D:\Test>echo "goodbye!"
"goodbye!"

Hope this helps.

Kyle Muir
  • 3,875
  • 2
  • 22
  • 27
  • Thanks Kyle. Let me elaborate the question . The above command does not work if I open a commnad window from powershell and then give the shell specific commands as two steps. I was trying something like this to issue commands from the app window : $help = "app help" $cmdline = "app.lnk" (shortcut to open the shell with all envt settings) Invoke-Expression $cmdline $help I was expecting $cmdline to be invoked and the rest of the commands to be called from that shell. Is that possible? – user1575430 Jun 20 '13 at 15:30
  • Is there any reason why you cant set up the environment settings in powershell rather than cmd and then simply call $help from within powershell? – Kyle Muir Jun 20 '13 at 19:29
  • Thanks for the reply. The script hangs indefinitely with the above approach. I am not sure how I could setup all the environment variables - usually I just launch the application with the shortcut – user1575430 Jun 20 '13 at 22:47
  • This article covers how to use Set\Use Environment Variables in PS: http://technet.microsoft.com/en-us/library/ff730964.aspx – Kyle Muir Jun 20 '13 at 23:25
1

I'm not sure, but I think what you want is the ability to have a script send input to and receive output from another program, where the other program has "state" that your script needs to be able to interact with. Below is an example of a script that drives CMD.EXE. CMD has state, such as current working directory and environment variables.

Note, that you could do what the other answerer suggested and just start the program, give all the input on the command line, and then do what you need to with the output. However for CMD if you need to make decisions based on the output, and then give CMD more input based on the previous output, you'd have to save and restore the environment and current working directories between each time you executed CMD. The approach below doesn't require that.

However the approach below does have several caveats. First it is dependent on the PS "host". It works (for me) on the command line PS, but not in ISE. This dependency is due to using the Raw host interface to determine if a key is available. Second it is timing dependent, based on the behavior of CMD (or whatever you use instead). You'll see a few sleep commands in the script. I had to experiment a whole lot to get this script to show CMD's output for a particular sub-command when that command was entered, versus CMD giving the output of previous commands after another command was entered. Comment out the sleeps to see what I mean. Third it is easy to hang Powershell. Killing CMD in task manager gets you out of the hung state, which I had to do many times.

You'll see that I added a couple of commands that the script deals with specially. This is to demonstrate that input to command can come from a PS script (versus input from the keyboard).

$global:ver++
if ($ExecutionContext.Host.name -match "ISE Host$") {
    write-warning "This script relies on RawUI functionality not implemented in ISE"
    return
}
$in = $null
$flExiting = $false

$doDebug = $false
function dot-debug {param($color) 
  if ($doDebug) {
    write-host "." -NoNewline -ForegroundColor $color
  }
}
#function dot-debug {param($color) }

$procInfo = new diagnostics.processstartinfo
$procInfo.RedirectStandardOutput=1
$procInfo.RedirectStandardInput=1
$procInfo.RedirectStandardError=1
$procInfo.FileName="cmd.exe"
$procInfo.UseShellExecute=0
$p=[diagnostics.process]::start($procInfo)
$outBuf = new char[] 4096
write-host "Version $ver"
sleep -Milliseconds 300
do {
   dot-debug red

  # This while loop determines whether input is available from either
  #  CMD's standard output or from the user typing. You don't want to
  #  get stuck waiting for input from either one if it doesn't really have input.

  :WaitIO  while ($true) {
    if (-1 -ne $p.StandardOutput.peek()) {
      dot-debug yellow
      $cnt = $p.StandardOutput.read( $outBuf, 0, 4096)
    } else {
      dot-debug Gray
      if ($host.ui.rawui.KeyAvailable -or $flExiting) {break}
    }
    $str = $outBuf[0..($cnt-1)] -join ""
    write-host "$str" -NoNewline

    while (-1 -eq ($rc =$p.StandardOutput.peek())) {
      if ($host.ui.rawui.KeyAvailable -or $flExiting) {
        break WaitIO
      }
      dot-debug DarkGray
      sleep -milli 200
    }
    dot-debug cyan
  }
  dot-debug green

  # read-host echoes input, so commands get echoed twice (cmd also echoes)
  #
  # $host.ui.rawui.ReadKey("NoEcho, IncludeKeyDown") doesn't work on ISE,
  # but does work in the PS cli shell
  if ($in -ne "exit") {$in = read-host}
  if ($in -eq "td") { # toggle debug
    $doDebug = -not $doDebug
    $p.StandardInput.WriteLine( "echo debug toggled")
    sleep -milli 300
    continue
  }
  if ($in -eq "xxx") {
    # Example of script driven output being sent to CMD
    $p.StandardInput.WriteLine( "echo This is a very long command that I do not want to have to type in everytime I want to use it")
    # You have to give CMD enough time to process command before you read stdout,
    # otherwise stdout gets "stuck" until the next time you write to stdin
    sleep -milli 1
    continue
  }
  if ($in -eq "exit") {
    $flExiting = $true
    $p.StandardInput.WriteLine($in)
    continue
  }

  foreach ($char in [char[]]$in) {
    $p.StandardInput.Write($char)
  }
  $p.StandardInput.Write("`n")
  sleep -milli 1

} until ($p.StandardOutput.EndOfStream)
Χpẘ
  • 3,403
  • 1
  • 13
  • 22
  • Thanks for your reply. what is ISE hear mean? I am trying to run and understand the script commands to fit my requirements. Will post back with the progress. – user1575430 Jun 24 '13 at 01:46
  • Powershell Integrated Script Environment. It is a little like Visual Studio for Powershell (but much simpler). If you look at Accessories, Powershell from your Start Menu you will see an icon to start "Windows Powershell ISE". – Χpẘ Jun 27 '13 at 01:01