Perl and PHP do this with backticks. For example,
$output = `ls`;
Returns a directory listing. A similar function, system(\"foo\")
Haskell:
import Control.Exception
import System.IO
import System.Process
main = bracket (runInteractiveCommand "ls") close $ \(_, hOut, _, _) -> do
output <- hGetContents hOut
putStr output
where close (hIn, hOut, hErr, pid) =
mapM_ hClose [hIn, hOut, hErr] >> waitForProcess pid
With MissingH installed:
import System.Cmd.Utils
main = do
(pid, output) <- pipeFrom "ls" []
putStr output
forceSuccess pid
This is an easy operation in "glue" languages like Perl and Ruby, but Haskell isn't.
J:
output=:2!:0'ls'
stream := open("ls", "p")
while line := read(stream) do {
# stuff
}
The docs call this a pipe. One of the good things is that it makes the output look like you're just reading a file. It also means you can write to the app's stdin, if you must.
Years ago I wrote a plugin for jEdit that interfaced to a native application. This is what I used to get the streams off the running executable. Only thing left to do is while((String s = stdout.readLine())!=null){...}
:
/* File: IOControl.java
*
* created: 10 July 2003
* author: dsm
*/
package org.jpop.io;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
/**
* Controls the I/O for a process. When using the std[in|out|err] streams, they must all be put on
* different threads to avoid blocking!
*
* @author dsm
* @version 1.5
*/
public class IOControl extends Object {
private Process process;
private BufferedReader stdout;
private BufferedReader stderr;
private PrintStream stdin;
/**
* Constructor for the IOControl object
*
* @param process The process to control I/O for
*/
public IOControl(Process process) {
this.process = process;
this.stdin = new PrintStream(process.getOutputStream());
this.stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
this.stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
}
/**
* Gets the stdin attribute of the IOControl object
*
* @return The stdin value
*/
public PrintStream getStdin() {
return this.stdin;
}
/**
* Gets the stdout attribute of the IOControl object
*
* @return The stdout value
*/
public BufferedReader getStdout() {
return this.stdout;
}
/**
* Gets the stderr attribute of the IOControl object
*
* @return The stderr value
*/
public BufferedReader getStderr() {
return this.stderr;
}
/**
* Gets the process attribute of the IOControl object. To monitor the process (as opposed to
* just letting it run by itself) its necessary to create a thread like this: <pre>
*. IOControl ioc;
*.
*. new Thread(){
*. public void run(){
*. while(true){ // only necessary if you want the process to respawn
*. try{
*. ioc = new IOControl(Runtime.getRuntime().exec("procname"));
*. // add some code to handle the IO streams
*. ioc.getProcess().waitFor();
*. }catch(InterruptedException ie){
*. // deal with exception
*. }catch(IOException ioe){
*. // deal with exception
*. }
*.
*. // a break condition can be included here to terminate the loop
*. } // only necessary if you want the process to respawn
*. }
*. }.start();
* </pre>
*
* @return The process value
*/
public Process getProcess() {
return this.process;
}
}
Why there is still no c# guy here :)
This is how to do it in C#. The built-in way.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "cmd";
p.StartInfo.Arguments = "/c dir";
p.Start();
string res = p.StandardOutput.ReadToEnd();
Console.WriteLine(res);
}
}
}
C# 3.0, less verbose than this one:
using System;
using System.Diagnostics;
class Program
{
static void Main()
{
var info = new ProcessStartInfo("cmd", "/c dir") { UseShellExecute = false, RedirectStandardOutput = true };
Console.WriteLine(Process.Start(info).StandardOutput.ReadToEnd());
}
}
Caveat: Production code should properly dispose the Process object...