Re: controlling cmd.exe via named pipes
- From: Rob Kennedy <me3@xxxxxxxxxxx>
- Date: Mon, 26 Feb 2007 21:59:56 -0600
toottifrootti@xxxxxxxx wrote:
<I've already posted this same discussion on
it.comp.lang.delphi and borland.public.delphi.language.delphi.general
without
receiving answer as I hoped to, so I re-post it here, hoping this
doesn't offend
any groups' netiquette. If so, I'm sorry.>
Why does no one respond to messages I post to Borland’s newsgroups?
http://www.cs.wisc.edu/~rkennedy/borland-newsgroups
I'm trying to use CreateProcess API to launch an "invisible" instance
of cmd.exe and control it via named pipes.
In order to do so, I use TPipeServer and TPipeClient components which
can be found on Russell's Delphi Pages
(http://users.adelphia.net/~rllibby/source.html), Pipes.zip file.
I use them to avoid handling named pipes directly by Windows
Pipes API. You could say this is discussible, anyway let's go on.
This is how I proceed:
1-I create two different named pipes, say 'cmdIN' and 'cmdOUT';
2-as suggested in th following thread ( http://tinyurl.com/2pmls6 ),
I
fill in a STARTUPINFO structure in the appropriate way, and then I
create the cmd.exe process:
=============================
stupinfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
stupinfo.hStdInput := <handle to the 'cmdIN' serverside,obtained from
the wrapping TPipeServer>
stupinfo.hStdOutput := <handle to the 'cmdOUT' clientside, obt from
the wrapping TPipeClient>
stupinfo.hStdError := <as above>
stupinfo.wShowWindow := SW_HIDE;
proc_name := 'C:\WINDOWS\system32\cmd.exe';
I hope that's not your real code. My computer doesn't even have a C: drive, and my OS directory is not named Windows.
If you want to know the name of the system's command interpreter, read the COMSPEC environment variable.
proc_string := '/K';
That's the command switch that tells Cmd to run the command on the command line, and then wait for more commands. If there is no command on the command line, then there's no reason to use /k. Run the program without any parameters, just as though you had double-clicked it in Explorer.
hcp := CreateProcess(proc_name, proc_string, nil, nil, TRUE, 0, nil,
nil, stupInfo, info);
A name like hcp suggests that the variable holds a handle value. CreateProcess returns a Bool, not a handle.
if hcp then WaitForSingleObject(info.hProcess, 3000);
Why are you waiting 3 seconds for the program to terminate, and then not paying attention to whether the program has actually terminated?
=============================
3-from my GUI application, I control the serverside of 'cmdOUT' and
the clientside of 'cmdIN';
I then send (using a TEdit) commands meant for cmd.exe writing on the
second one, catching on the first one the incoming message events,
and
finally copying these messages on a TMemo.
As soon as the process is created, on the memo an "Invalid handle"
message appears,
Messages don't just appear. What is the cause of that message? Where does it come from? Any indication of what handle it's talking about?
and from then on, cmd.exe does not react to commands
I send to it, eve though it receives them.
And I say "even though it receives them" because I also catch
incoming
message events on the serverside of 'cmdIN': commands regularly reach
the other end of the pipe, but they do not have any effect at all,
even if cmd.exe is still alive, as task manager allows to verify.
So, you're sending stuff to the command interpreter, and you're receiving responses. Then what's the problem? What effect are your commands supposed to have, and how are you observing them?
I suppose the cause's the following.
Both the TPipeServer that wraps 'cmdIN' serverside and similarly the
TPipeClient that wraps 'cmdOUT' clientside have a thread dedicated to
listening incoming messages. Maybe
duplicating handles to those pipe sides would be better than passing
to cmd.exe the handles owned by those threads.
Threads don't own handles.
The threads are important, though, since without them you'd get deadlock.
Anyway -I'm sorry for my long, complicated and a bit dazed thread-,
can anyone help me?
Is my last guess correct, and if so, how to correctly duplicate those
handle?
Call DuplicateHandle. Make sure the new handle values are inheritable. Both the source and target processes will be your program's process. You can duplicate them into Cmd's process because that process doesn't exist yet. Duplicate them in your own process, and pass the new handles to CreateProcess.
Res := DuplicateHandle(GetCurrentProcess, cmdIn, GetCurrentProcess, NewCmdIn, 0, True, Duplicate_Same_Access);
Win32Check(Res);
--
Rob
.
- References:
- controlling cmd.exe via named pipes
- From: toottifrootti
- controlling cmd.exe via named pipes
- Prev by Date: Re: React when the program isn't focused
- Next by Date: Re: React when the program isn't focused
- Previous by thread: controlling cmd.exe via named pipes
- Index(es):
Relevant Pages
|