www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Spawning a console in Windows (similar to forkpty on linux)

reply "wobbles" <grogan.colin gmail.com> writes:
This isn't specifically a D question, but seeing as it's for a D 
library I figure it can go here :)

On Windows, I want to be able to spawn a console and then 
interact with its stdin/out asynchronously, similar to how 
forkpty [1] works on linux.

I'm improving my dexpect library [2] to work with windows 
machines and this bit has me stumped. There doesnt seem to be 
much info about it that I can find (though my google-fu mightn't 
be good enough!!)

I'm sure theres someone here who knows something?

Thanks!

[1] http://linux.die.net/man/3/forkpty
[2] https://github.com/grogancolin/dexpect
May 09 2015
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 10/05/2015 12:13 a.m., wobbles wrote:
 This isn't specifically a D question, but seeing as it's for a D library
 I figure it can go here :)

 On Windows, I want to be able to spawn a console and then interact with
 its stdin/out asynchronously, similar to how forkpty [1] works on linux.

 I'm improving my dexpect library [2] to work with windows machines and
 this bit has me stumped. There doesnt seem to be much info about it that
 I can find (though my google-fu mightn't be good enough!!)

 I'm sure theres someone here who knows something?

 Thanks!

 [1] http://linux.die.net/man/3/forkpty
 [2] https://github.com/grogancolin/dexpect
Did you try creating a new process which is cmd? Because std.process should be able to handle the IO part.
May 09 2015
parent reply "wobbles" <grogan.colin gmail.com> writes:
On Saturday, 9 May 2015 at 12:16:52 UTC, Rikki Cattermole wrote:
 On 10/05/2015 12:13 a.m., wobbles wrote:
 This isn't specifically a D question, but seeing as it's for a 
 D library
 I figure it can go here :)

 On Windows, I want to be able to spawn a console and then 
 interact with
 its stdin/out asynchronously, similar to how forkpty [1] works 
 on linux.

 I'm improving my dexpect library [2] to work with windows 
 machines and
 this bit has me stumped. There doesnt seem to be much info 
 about it that
 I can find (though my google-fu mightn't be good enough!!)

 I'm sure theres someone here who knows something?

 Thanks!

 [1] http://linux.die.net/man/3/forkpty
 [2] https://github.com/grogancolin/dexpect
Did you try creating a new process which is cmd? Because std.process should be able to handle the IO part.
I have, but they all block i/o and so I cant continually read from its output :/
May 09 2015
parent reply "wobbles" <grogan.colin gmail.com> writes:
On Saturday, 9 May 2015 at 12:25:32 UTC, wobbles wrote:
 On Saturday, 9 May 2015 at 12:16:52 UTC, Rikki Cattermole wrote:
 On 10/05/2015 12:13 a.m., wobbles wrote:
 This isn't specifically a D question, but seeing as it's for 
 a D library
 I figure it can go here :)

 On Windows, I want to be able to spawn a console and then 
 interact with
 its stdin/out asynchronously, similar to how forkpty [1] 
 works on linux.

 I'm improving my dexpect library [2] to work with windows 
 machines and
 this bit has me stumped. There doesnt seem to be much info 
 about it that
 I can find (though my google-fu mightn't be good enough!!)

 I'm sure theres someone here who knows something?

 Thanks!

 [1] http://linux.die.net/man/3/forkpty
 [2] https://github.com/grogancolin/dexpect
Did you try creating a new process which is cmd? Because std.process should be able to handle the IO part.
I have, but they all block i/o and so I cant continually read from its output :/
What I mean is, if the cmd.exe hasnt flushed it's output, my cmdPid.stdout.readln (or whatever) will block until it does. I dont really want this. I guess I need to make another thread to do this so I wont block the main thread?
May 09 2015
parent reply "Kagamin" <spam here.lot> writes:
On Saturday, 9 May 2015 at 12:26:58 UTC, wobbles wrote:
 What I mean is, if the cmd.exe hasnt flushed it's output, my 
 cmdPid.stdout.readln (or whatever) will block until it does. I 
 dont really want this.
Are you sure cmd is the culprit? It should have sensible buffering. Also do you want just a console window or also a command interpreter attached to it?
May 09 2015
parent reply "wobbles" <grogan.colin gmail.com> writes:
On Saturday, 9 May 2015 at 12:48:16 UTC, Kagamin wrote:
 On Saturday, 9 May 2015 at 12:26:58 UTC, wobbles wrote:
 What I mean is, if the cmd.exe hasnt flushed it's output, my 
 cmdPid.stdout.readln (or whatever) will block until it does. I 
 dont really want this.
Are you sure cmd is the culprit? It should have sensible buffering. Also do you want just a console window or also a command interpreter attached to it?
My windows knowledge isnt marvelous, but I believe I'll need the interpreter attached. Just as an example of running cmd through std.process, running this on my system: auto pipes = pipeShell("cmd.exe"); write(pipes.stdout.readln); write(pipes.stdout.readln); write(pipes.stdout.readln); return; will print ` Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. ` and then exits. However, adding another "write" line before the return; will cause the program to hang there, waiting for the cmd.exe process to flush it's next line. On Linux, I'm able to edit a file descriptor after I've created it to tell it to read/write asynchronously, I cant seem to find anything similar on windows however.
May 09 2015
next sibling parent reply "wobbles" <grogan.colin gmail.com> writes:
On Saturday, 9 May 2015 at 13:00:01 UTC, wobbles wrote:
 On Saturday, 9 May 2015 at 12:48:16 UTC, Kagamin wrote:
 On Saturday, 9 May 2015 at 12:26:58 UTC, wobbles wrote:
 What I mean is, if the cmd.exe hasnt flushed it's output, my 
 cmdPid.stdout.readln (or whatever) will block until it does. 
 I dont really want this.
Are you sure cmd is the culprit? It should have sensible buffering. Also do you want just a console window or also a command interpreter attached to it?
My windows knowledge isnt marvelous, but I believe I'll need the interpreter attached. Just as an example of running cmd through std.process, running this on my system: auto pipes = pipeShell("cmd.exe"); write(pipes.stdout.readln); write(pipes.stdout.readln); write(pipes.stdout.readln); return; will print ` Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. ` and then exits. However, adding another "write" line before the return; will cause the program to hang there, waiting for the cmd.exe process to flush it's next line. On Linux, I'm able to edit a file descriptor after I've created it to tell it to read/write asynchronously, I cant seem to find anything similar on windows however.
Spoke too soon. Looks like this is what I need: http://www.codeproject.com/Articles/534/An-Introduction-to-Processes-Asynchronous-Process
May 09 2015
parent reply "Baz" <bb.temp gmx.com> writes:
On Saturday, 9 May 2015 at 13:01:27 UTC, wobbles wrote:
 On Saturday, 9 May 2015 at 13:00:01 UTC, wobbles wrote:
 On Saturday, 9 May 2015 at 12:48:16 UTC, Kagamin wrote:
 On Saturday, 9 May 2015 at 12:26:58 UTC, wobbles wrote:
 What I mean is, if the cmd.exe hasnt flushed it's output, my 
 cmdPid.stdout.readln (or whatever) will block until it does. 
 I dont really want this.
Are you sure cmd is the culprit? It should have sensible buffering. Also do you want just a console window or also a command interpreter attached to it?
My windows knowledge isnt marvelous, but I believe I'll need the interpreter attached. Just as an example of running cmd through std.process, running this on my system: auto pipes = pipeShell("cmd.exe"); write(pipes.stdout.readln); write(pipes.stdout.readln); write(pipes.stdout.readln); return; will print ` Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. ` and then exits. However, adding another "write" line before the return; will cause the program to hang there, waiting for the cmd.exe process to flush it's next line. On Linux, I'm able to edit a file descriptor after I've created it to tell it to read/write asynchronously, I cant seem to find anything similar on windows however.
Spoke too soon. Looks like this is what I need: http://www.codeproject.com/Articles/534/An-Introduction-to-Processes-Asynchronous-Process
You need a loop that run until the PID is invalid. something like: --- while(true) { Thread.sleep(dur!"msecs"(10)); // operation on i/o streams write(pipes.stdout.readln); if (pipes.pid.tryWait.terminated) break; } --- also note that the piped process needs its whole output to be read before it terminates, otherwise it can stick (never ends).
May 09 2015
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 9 May 2015 at 18:19:16 UTC, Baz wrote:
 You need a loop that run until the PID is invalid.
You could also call WaitForSingleObject on the process handle https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx The HANDLE it expects can be gotten from std.process with this http://dlang.org/phobos/std_process.html#osHandle But then you'll block for it to end so it probably isn't what you really want...
May 09 2015
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 9 May 2015 at 13:00:01 UTC, wobbles wrote:
 On Linux, I'm able to edit a file descriptor after I've created 
 it to tell it to read/write asynchronously, I cant seem to find 
 anything similar on windows however.
Asynchronous I/O on Windows is called "Overlapped I/O". It is a bit involved to use though, especially since D by default doesn't come with all the necessary headers. You can download the win32 api bindings or you can just declare the bits as needed. My terminal emulator uses overlapped I/O and a spawned process (and on Linux, it uses forkpty!) to talk to ssh on Windows. https://github.com/adamdruppe/terminal-emulator/blob/master/terminalemulator.d I had to write a function to make an async pipe, then spawn a process using them, then get and send data. I also declared all the needed functions myself. A lot of code to go through but it is a working example... a few things to look for are MyCreatePipeEx, CreateProcess, the word 'overlapped', ReadFileEx, and the simpledisplay.d library it imports also uses SleepEx which lets other things trigger.
May 09 2015
parent "wobbles" <grogan.colin gmail.com> writes:
On Saturday, 9 May 2015 at 23:32:49 UTC, Adam D. Ruppe wrote:
 On Saturday, 9 May 2015 at 13:00:01 UTC, wobbles wrote:
 On Linux, I'm able to edit a file descriptor after I've 
 created it to tell it to read/write asynchronously, I cant 
 seem to find anything similar on windows however.
Asynchronous I/O on Windows is called "Overlapped I/O". It is a bit involved to use though, especially since D by default doesn't come with all the necessary headers. You can download the win32 api bindings or you can just declare the bits as needed. My terminal emulator uses overlapped I/O and a spawned process (and on Linux, it uses forkpty!) to talk to ssh on Windows. https://github.com/adamdruppe/terminal-emulator/blob/master/terminalemulator.d I had to write a function to make an async pipe, then spawn a process using them, then get and send data. I also declared all the needed functions myself. A lot of code to go through but it is a working example... a few things to look for are MyCreatePipeEx, CreateProcess, the word 'overlapped', ReadFileEx, and the simpledisplay.d library it imports also uses SleepEx which lets other things trigger.
Thanks adam, this is very helpful!
May 11 2015
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
On Saturday, 9 May 2015 at 13:00:01 UTC, wobbles wrote:
 Just as an example of running cmd through std.process, running 
 this on my system:
 	auto pipes = pipeShell("cmd.exe");
 	write(pipes.stdout.readln);
 	write(pipes.stdout.readln);
 	write(pipes.stdout.readln);
         return;
 will print
 `
 Microsoft Windows [Version 6.3.9600]
 (c) 2013 Microsoft Corporation. All rights reserved.

 `
 and then exits.

 However, adding another "write" line before the return; will 
 cause the program to hang there, waiting for the cmd.exe 
 process to flush it's next line.
I guess, the last (prompt) line is properly flushed, it just doesn't have EOL, that's why readln won't return it. See if stdout has a method to read/peek whatever data it has without waiting for EOL.
May 10 2015
prev sibling parent "Kagamin" <spam here.lot> writes:
On Saturday, 9 May 2015 at 13:00:01 UTC, wobbles wrote:
 My windows knowledge isnt marvelous, but I believe I'll need 
 the interpreter attached.
If you only need the interpreter, pipeProcess should be fine, it's a normal program like anything else, just interactive.
May 10 2015