# Can I run windows command line app interactively?

**URL:** <https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724>\
**Category:** ruby-talk\
**Created:** [4 November 2010 08:52 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724 "2010-11-04T08:52:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cai\_I](https://avatars.discourse-cdn.com/v4/letter/c/ea666f/32.png) [@Cai\_I](https://rubytalk.org/u/Cai_I)\
**Post date:** [4 November 2010 08:52 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/1 "2010-11-04T08:52:59Z")

</div>

I want to do something like this:

&nbsp;&nbsp;&nbsp;&nbsp;# open a session  
&nbsp;&nbsp;&nbsp;&nbsp;@session = IO.popen('cmd.exe', 'r+')

&nbsp;&nbsp;&nbsp;&nbsp;# run a command and process outputs  
&nbsp;&nbsp;&nbsp;&nbsp;@session.puts('dir')  
&nbsp;&nbsp;&nbsp;&nbsp;@session.each do |line|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;# run a command line application  
&nbsp;&nbsp;&nbsp;&nbsp;@session.puts('robocopy.exe ......')  
&nbsp;&nbsp;&nbsp;&nbsp;@session.each do |line|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
&nbsp;&nbsp;&nbsp;&nbsp;end

The issue is that "@session.each" never stop. It waits when cmd.exe  
waiting for input. So the scripts hang.

Thanks!

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Jeremy\_Bopp](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/jeremy_bopp/32/1937_2.png) [@Jeremy\_Bopp](https://rubytalk.org/u/Jeremy_Bopp)\
**Post date:** [4 November 2010 16:14 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/2 "2010-11-04T16:14:48Z")

</div>

The problem is that @session.each will run until the input stream is  
closed, in this case until cmd.exe exits. What you want to do is have  
it run only until you get the next prompt waiting for input. For that  
you need to use something like the expect module:

require 'expect'  
session = IO.popen('cmd.exe', 'r+')  
session.puts('dir')  
session.expect(/[CD]:\\.\*\>/) do  
&nbsp;&nbsp;session.puts('robocopy.exe ......')  
end  
session.expect(/[CD]:\\.\*\>/) do  
&nbsp;&nbsp;session.puts('exit')  
end  
session.close

The only problem with this solution is that you won't be able to see the  
output of the commands you run this way. That output is consumed by  
#expect, and I don't know of a way to make it print what it consumes.  
Of course another way to handle your exact example is something like this:

system('dir && robocopy.exe .......')

As long as you don't intend to process the output of commands along the  
way in order to change how you run the subsequent commands, this should  
work for you. If you \*do\* want to process the output then you could run  
each command in a separate session and read the output in between each  
session:

session = IO.popen('dir')  
session.each do |line|  
&nbsp;&nbsp;puts line  
end  
session.close

session = IO.popen('robocopy.exe .....')  
session.each do |line|  
&nbsp;&nbsp;puts line  
end  
session.close

-Jeremy

> **···**
>
> On 11/4/2010 3:52 AM, Cai I. wrote:
> 
> > I want to do something like this:
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;# open a session  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session = IO.popen('cmd.exe', 'r+')
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;# run a command and process outputs  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session.puts('dir')  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session.each do |line|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
> > &nbsp;&nbsp;&nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;# run a command line application  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session.puts('robocopy.exe ......')  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session.each do |line|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
> > &nbsp;&nbsp;&nbsp;&nbsp;end
> > 
> > The issue is that "@session.each" never stop. It waits when cmd.exe  
> > waiting for input. So the scripts hang.

---

<div class="post-metadata">

**Author:** ![Charles\_Calvert](https://avatars.discourse-cdn.com/v4/letter/c/e19b73/32.png) [@Charles\_Calvert](https://rubytalk.org/u/Charles_Calvert)\
**Post date:** [10 November 2010 18:55 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/3 "2010-11-10T18:55:13Z")

</div>

wrote in \<ea0055cfedb122c2ed0424aaf5e406c0@ruby-forum.com\>:

> I want to do something like this:
> 
> &nbsp;&nbsp;&nbsp;# open a session  
> &nbsp;&nbsp;&nbsp;@session = IO.popen('cmd.exe', 'r+')
> 
> &nbsp;&nbsp;&nbsp;# run a command and process outputs  
> &nbsp;&nbsp;&nbsp;@session.puts('dir')  
> &nbsp;&nbsp;&nbsp;@session.each do |line|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;# run a command line application  
> &nbsp;&nbsp;&nbsp;@session.puts('robocopy.exe ......')  
> &nbsp;&nbsp;&nbsp;@session.each do |line|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
> &nbsp;&nbsp;&nbsp;end

You can do this, but you'll need to use the Win32 API to attach to a  
console (command shell) and be able to read and write to its STDIN and  
STDOUT. See the links below:

\<[http://www.dreamincode.net/code/snippet921.htm&gt](http://www.dreamincode.net/code/snippet921.htm&gt);  
\<[http://www.halcyon.com/~ast/dload/guicon.htm&gt](http://www.halcyon.com/~ast/dload/guicon.htm&gt);  
\<[Microsoft Learn: Build skills that open doors in your career](http://msdn.microsoft.com/en-us/library/ms681944%28VS.85%29.aspx&gt);

The first two are links to examples, and the last is to the MSDN  
documentation. It's been a number of years since I did this, but it's  
the technique that Visual Studio uses to run the command-line  
compilers and pipe their output back into the IDE.

> **···**
>
> On Thu, 4 Nov 2010 03:52:59 -0500, "Cai I." \<cai.inception@gmail.com\>
> 
> --  
> Charles Calvert | Software Design/Development  
> Celtic Wolf, Inc. | Project Management  
> [http://www.celticwolf.com/](http://www.celticwolf.com/) | Technical Writing  
> (703) 580-0210 | Research

---

<div class="post-metadata">

**Author:** ![Cai\_I](https://avatars.discourse-cdn.com/v4/letter/c/ea666f/32.png) [@Cai\_I](https://rubytalk.org/u/Cai_I)\
**Post date:** [10 November 2010 18:38 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/4 "2010-11-10T18:38:09Z")

</div>

Jeremy Bopp wrote in post #959348:

> > &nbsp;&nbsp;&nbsp;&nbsp;# run a command line application  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session.puts('robocopy.exe ......')  
> > &nbsp;&nbsp;&nbsp;&nbsp;@session.each do |line|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p line  
> > &nbsp;&nbsp;&nbsp;&nbsp;end
> > 
> > The issue is that "@session.each" never stop. It waits when cmd.exe  
> > waiting for input. So the scripts hang.
> 
> The problem is that @session.each will run until the input stream is  
> closed, in this case until cmd.exe exits. What you want to do is have  
> it run only until you get the next prompt waiting for input. For that  
> you need to use something like the expect module:
> 
> require 'expect'  
> session = IO.popen('cmd.exe', 'r+')  
> session.puts('dir')  
> session.expect(/[CD]:\\.\*\>/) do  
> &nbsp;&nbsp;session.puts('robocopy.exe ......')  
> end  
> session.expect(/[CD]:\\.\*\>/) do  
> &nbsp;&nbsp;session.puts('exit')  
> end  
> session.close
> 
> The only problem with this solution is that you won't be able to see the  
> output of the commands you run this way. That output is consumed by  
> #expect, and I don't know of a way to make it print what it consumes.  
> Of course another way to handle your exact example is something like  
> this:
> 
> system('dir && robocopy.exe .......')
> 
> As long as you don't intend to process the output of commands along the  
> way in order to change how you run the subsequent commands, this should  
> work for you. If you \*do\* want to process the output then you could run  
> each command in a separate session and read the output in between each  
> session:
> 
> session = IO.popen('dir')  
> session.each do |line|  
> &nbsp;&nbsp;puts line  
> end  
> session.close
> 
> session = IO.popen('robocopy.exe .....')  
> session.each do |line|  
> &nbsp;&nbsp;puts line  
> end  
> session.close
> 
> -Jeremy

Thanks a lot Jeremy for reply.

I have to get the output for parsing in my scenario, and I finally got  
it done by monitoring the output and stop read when the prompt found, I  
guess it likes what the "expect" does. If no prompt found, I will parse  
out each line and get it processed.

I found the function ios.readpartial() very useful in this scenario. I  
use it to read output from cmd.exe. It won't get blocked at the end of  
output as long as it has read something. I guess it just read what in  
the system buffer and return and it only block when nothing left in  
buffer to read.

> **···**
>
> > On 11/4/2010 3:52 AM, Cai I. wrote:
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Cai\_I](https://avatars.discourse-cdn.com/v4/letter/c/ea666f/32.png) [@Cai\_I](https://rubytalk.org/u/Cai_I)\
**Post date:** [13 November 2010 03:50 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/5 "2010-11-13T03:50:32Z")

</div>

Charles Calvert wrote in post #960600:

> You can do this, but you'll need to use the Win32 API to attach to a  
> console (command shell) and be able to read and write to its STDIN and  
> STDOUT. See the links below:
> 
> \<[http://www.dreamincode.net/code/snippet921.htm&gt](http://www.dreamincode.net/code/snippet921.htm&gt);  
> \<[http://www.halcyon.com/~ast/dload/guicon.htm&gt](http://www.halcyon.com/~ast/dload/guicon.htm&gt);  
> \<[Microsoft Learn: Build skills that open doors in your career](http://msdn.microsoft.com/en-us/library/ms681944%28VS.85%29.aspx&gt);
> 
> The first two are links to examples, and the last is to the MSDN  
> documentation. It's been a number of years since I did this, but it's  
> the technique that Visual Studio uses to run the command-line  
> compilers and pipe their output back into the IDE.

Thanks Charles, this looks promising.

One little question is whether the ruby program need to create another  
process for the new console? the MSDN doc says "A process can be  
associated with only one console, so the AllocConsole function fails if  
the calling process already has a console. A process can use the  
FreeConsole function to detach itself from its current console, then it  
can call AllocConsole to create a new console or AttachConsole to attach  
to another console.If the calling process creates a child process, the  
child inherits the new console."

I am not familiar with calling Win AP in ruby, but I will surely take it  
a try when I got time later.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Charles\_Calvert](https://avatars.discourse-cdn.com/v4/letter/c/e19b73/32.png) [@Charles\_Calvert](https://rubytalk.org/u/Charles_Calvert)\
**Post date:** [13 November 2010 15:45 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/6 "2010-11-13T15:45:18Z")

</div>

On Fri, 12 Nov 2010 22:50:32 -0500, Cai Inception  
\<cai.inception@gmail.com\> wrote in  
\<422bf4524ffd3e8cb2b513afdca90793@ruby-forum.com\>:

> Charles Calvert wrote in post #960600:
> 
> > You can do this, but you'll need to use the Win32 API to attach to a  
> > console (command shell) and be able to read and write to its STDIN and  
> > STDOUT. See the links below:
> > 
> > \<[http://www.dreamincode.net/code/snippet921.htm&gt](http://www.dreamincode.net/code/snippet921.htm&gt);  
> > \<[http://www.halcyon.com/~ast/dload/guicon.htm&gt](http://www.halcyon.com/~ast/dload/guicon.htm&gt);  
> > \<[Microsoft Learn: Build skills that open doors in your career](http://msdn.microsoft.com/en-us/library/ms681944%28VS.85%29.aspx&gt);
> > 
> > The first two are links to examples, and the last is to the MSDN  
> > documentation. It's been a number of years since I did this, but it's  
> > the technique that Visual Studio uses to run the command-line  
> > compilers and pipe their output back into the IDE.
> 
> Thanks Charles, this looks promising.

You're welcome.

> One little question is whether the ruby program need to create another  
> process for the new console? the MSDN doc says "A process can be  
> associated with only one console, so the AllocConsole function fails if  
> the calling process already has a console. A process can use the  
> FreeConsole function to detach itself from its current console, then it  
> can call AllocConsole to create a new console or AttachConsole to attach  
> to another console.If the calling process creates a child process, the  
> child inherits the new console."

That's a good question. I've always done this from GUI apps where the  
use case was the same as Visual Studio's. As a result, the  
application didn't have a console allocated.

I guess it depends on what your use case is. Are you running the Ruby  
app via the MRI from a console, or is it a web app running via  
Apache/Nginx/etc.? In the latter case, I wouldn't think that you'd  
have a console allocated to the app. You could always call  
AllocConsole as a test to see what happens.

If your case is the former, then Jeremy Boop's suggestion might be the  
way to go. When I wrote my original reply, I was thinking of a GUI or  
webapp controlling the console app.

> **···**
>
> --  
> Charles Calvert | Software Design/Development  
> Celtic Wolf, Inc. | Project Management  
> [http://www.celticwolf.com/](http://www.celticwolf.com/) | Technical Writing  
> (703) 580-0210 | Research

---

<div class="post-metadata">

**Author:** ![Cai\_I](https://avatars.discourse-cdn.com/v4/letter/c/ea666f/32.png) [@Cai\_I](https://rubytalk.org/u/Cai_I)\
**Post date:** [17 November 2010 01:12 UTC](https://rubytalk.org/t/can-i-run-windows-command-line-app-interactively/60724/7 "2010-11-17T01:12:59Z")

</div>

Charles Calvert wrote in post #961204:

> If your case is the former, then Jeremy Boop's suggestion might be the  
> way to go. When I wrote my original reply, I was thinking of a GUI or  
> webapp controlling the console app.

My case is the former. I write scripts running regular jobs and they  
start in console with ruby.exe. So I will go wiht Jeremy Boop's  
suggestion. But still thanks for replying and clarifying, Charles.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).
