I'm having a problem redirecting a spawned processes output to a file.
After much mucking about with _dup and _dup2 as per CRTLibrary>>spawnForOutput:args: (and little success - never mind that I've done this before in C without trouble) I decided to try using CMD.EXE to run my command, using the /C switch to have it terminate nicely after running the command, and using CMD's I/O redirection (the '>' and '2>' operators on the command line) to do the I/O redirection. In all cases the temporary files are created properly, but nothing is ever written to them. The commands execute properly, but the output from them is not captured. A typical command line is cmd /C ci -u -m"Revised" -t-"Initial version" "RcsSourceManager.cls" >C:\TEMP\1771.tmp 2>C:\TEMP\1772.tmp (Pretend the above is all on one line). This command is being launched using KernelLibrary>>createProcess:lpCommandLine:lpProcessAttributes:lpThreadA ttributes:bInheritsHandles:dwCreationFlags:lpEnvironment:lpCurrentDirect ory:lpStartupInfo:lpProcessInformation:, and as I say the process runs fine and does its job properly. But, dang it, the output is never captured! Running the same command in a command-line window without the redirection shows the stuff being written to the screen as plain as day, and if I run it from a command-line window with the redirection included the output is redirected as expected. At first I thought it was because (perhaps) when running a GUI app that the standard files (stdin, stdout, and stderr) might not be defined, which is why I switched to launching CMD, to be (reasonably) sure that the standard I/O files would be present. I even tried switching the /C switch to /K when running CMD.EXE, hoping that would keep the window around so I could perhaps see what was going on, but the window just flashed up and disappeared no matter whether I used /C or /K. AGGGGHHHHHHH!!!!!!!!! <sigh> Can anyone shed some light on this? And/all help gratefully appreciated. -- Bob Jarvis Compuware @ Timken Sent via Deja.com http://www.deja.com/ Before you buy. |
Bob, just off the top of my head, try it without the the redirection, but with
" & pause" appended to the end of your command line. That should leave the output on the screen and force the window to stay open until you feed it a keystroke. Good luck. Don |
In article <9092jt$dt88$[hidden email]>,
"Don Rylander" <[hidden email]> wrote: > Bob, just off the top of my head, try it without the the redirection, but with > " & pause" appended to the end of your command line. That should leave the > output on the screen and force the window to stay open until you feed it a > keystroke. Good luck. Good thought, but it didn't work - the process terminated anyways. I even tried changed the /C flag to /K, but the window still slams shut. I've even tried dropping in a 'self halt' before I close the thread and process handles returned in the PROCESS_INFORMATION struct, but still no joy. HOWEVER - I have now gotten it to work with code borrowed and bastardized from CRTLibrary>>spawnForOutput:args:. By replacing the '_dup/_dup2' code in CRTLibrary>>spawnForOutput:args with command- line redirection it then works - but I still don't understand why the code which uses KernelLibrary>>createProcess:... *doesn't* work. Unfortunately the code borrowed from CRTLibrary doesn't let me control how the window is shown, so I get this command-line window which flashes up briefly, which is objectionable (to me - OK, I'm picky) so I really *want* to get the CreateProcess stuff working right. Still, progress is progress... :-) -- Bob Jarvis Compuware @ Timken Sent via Deja.com http://www.deja.com/ Before you buy. |
Hi Bob,
"Bob Jarvis" <[hidden email]> wrote in message news:9097mf$vc0$[hidden email]... > > HOWEVER - I have now gotten it to work with code borrowed and > bastardized from CRTLibrary>>spawnForOutput:args:. By replacing > the '_dup/_dup2' code in CRTLibrary>>spawnForOutput:args with command- > line redirection it then works - but I still don't understand why the > code which uses KernelLibrary>>createProcess:... *doesn't* work. > Unfortunately the code borrowed from CRTLibrary doesn't let me control > how the window is shown, so I get this command-line window which > flashes up briefly, which is objectionable (to me - OK, I'm picky) so I > really *want* to get the CreateProcess stuff working right. As you might have seen, I've been struggling in this same arena (see my threads Talking to Java and Talking to an external program a couple of weeks ago), and I didn't get it to work. I put it aside because of time constraints, but eventually I need to get it to work properly (I now just output to a file and pick up the file from within Smalltalk). Things that I tried and did not get to work: ShellLibrary>>shellOpen: ShellLibrary>>shellExecute: and the rest These should return a handle that should be able to be interpreted by StdioFileStream class>> fromHandle: handle KernelLibrary>>winExec:uCmdShow: KernelLibrary>>commandLine:toArgvW: Therefore I'm VERY interested in your progress, could you for example elaborate on your CRTLibrary>>spawnForOutput:args: solution? Thanks in advance, Ted |
In article <90fqtv$vk7n$[hidden email]>,
"Ted Bracht" <[hidden email]> wrote: > Therefore I'm VERY interested in your progress, could you for example > elaborate on your CRTLibrary>>spawnForOutput:args: solution? Here's the code which I plagiaraized from CRTLibrary>>spawnForOutput:args: which uses _spawnvp to fire off a console app, redirecting its output (in this case stderr only) to a file. There are several methods included so you can see precisely what happens: executeCommand: aStringCommand inDirectory: aDirectoryString waitForSeconds: anIntegerSeconds "Execute a command by spawning a new process and waiting until it completes." | tmpName tmpFile out argv args cmdString argString retval | tmpName := File temporaryFilename. cmdString := 'cmd'. argString := '/C "', (self doubleQuotesIn: (self driveFrom: aDirectoryString) , ' && cd "', aDirectoryString, '" && ', aStringCommand), '" 2>', tmpName. Transcript show: 'argString = ', argString; cr. "This is rather horrid, but we need a vector terminated by a null pointer" argv := DWORDArray new: 2. args := ' ', argString. argv at: 1 put: args yourAddress. retval := CRTLibrary default _spawnvp: 0 "_P_WAIT" cmdname: cmdString argv: argv. retval == -1 ifTrue: [self error: 'Fail to spawn ', cmdString]. tmpFile := FileStream read: tmpName. out := tmpFile contents. tmpFile close. " File delete: tmpName." ^out doubleQuotesIn: aString ^aString inject: '' into: [ :tot :each | each = $" ifTrue: [ tot, '""' ] ifFalse: [ tot, (String with: each) ]] driveFrom: aDirectoryString (aDirectoryString at: 2) = $: ifTrue: [ ^aDirectoryString leftString: 2 ] ifFalse: [ ^'' ] As you can see I'm only redirecting stderr here because that's the only file I really care about. I expect that redirection of stdout would work as well. For robustness the above code should check the COMSPEC environment variable to figure out which command-line interpreter to run, but for development purposes I've got it hardcoded as 'CMD'. I looked through the C runtime source included with VC++ 6 today, but that hasn't given me any great insights. I tried including the CREATE_NEW_CONSOLE flag into the dwCreationFlags argument to CreateProcess, thinking that might get me somewhere, but still no joy. The C runtime lib *does* do some funky playing around with the cbReserved2 and lpReserved2 fields in the STARTUPINFO struct but I don't *think* it's relevant. I've also tried setting the hStdOutput and hStdError handles, and adding STARTF_USESTDHANDLES to the dwFlags, *and* making sure that the bInheritHandles param to CreateProcess is set to 'true'. But <sigh> still no joy... -- Bob Jarvis Compuware @ Timken Sent via Deja.com http://www.deja.com/ Before you buy. |
Hi Bob,
I've been playing around a bit further, and the best I've come up with is to capture the command in a batch file and use KernelLibrary default winExec: 'c:\myBatch.bat' uCmdShow: 0 By using uCmdShow: 0 it actually suppresses the command window. Hope this helps, I'm still not there yet either. Ted |
In article <90kvqd$1eugr$[hidden email]>,
"Ted Bracht" <[hidden email]> wrote: > > I've been playing around a bit further, and the best I've come up with is to > capture the command in a batch file and use > > KernelLibrary default winExec: 'c:\myBatch.bat' uCmdShow: 0 > > By using uCmdShow: 0 it actually suppresses the command window. Thanks for the help. Given the above and a bit more fiddling around I think I've finally got something that I like. What I did was define a SHELLEXECUTEINFO class to map the Win32 structure of the same name in Dolphin, and then added the ShellExecuteEx command to ShellLibrary. This allows me to execute the batch file *and* get back a process handle I can wait on using WaitForSingleObject. I've got a couple of packages that provide this functionality. I can email them to you if you want to take a look at them. -- Bob Jarvis Compuware @ Timken Sent via Deja.com http://www.deja.com/ Before you buy. |
Free forum by Nabble | Edit this page |