Launching other programs from within Smalltalk

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Launching other programs from within Smalltalk

Bill Schwab-2
Bob,

> > Bob emailed me with a one-line change that appears to be the answer to
> > my problem.
>
> Hey, that's happened to all of us, and it'll happen again.  :-)

No doubt :)


> > Any comments on the stdout/stderr block idea?
>
> I guess I'm either too tired or too dense, but I don't understand how
> this would work.  Could you give a bit more explanation of what you're
> thinking of?  Code fragments of how you'd expect to use it would be a
> big help.

It's a pretty simple idea, and I'm not doing a very good job of explaining
it.  It might be easier to just write the wrapper that I have in mind, and
the applications will be obvious.  If you like it, we're done, and if not,
we can kick it around to get something better.  More to come.


> Thanks for helping to improve things.

Thanks for doing the hard part!

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Launching other programs from within Smalltalk

Schwab,Wilhelm K
Bob,

Here is another attempt at a helper method for ExternalProcess.  Rather
than collecting and returning the output, it accepts and evaluates two
blocks as follows:

ExternalProcess
        executeCommand:cmd contents
        inDirectory:( File splitPathFrom:each issFileName )
        waitForSeconds:30
        out:[ :text | out nextPutAll:text. ]
        error:[ :text | out nextPutAll:text. ].

Obviously, one could use different streams for the two kinds of output -
a "need" to do that started me thinking about this.

Note that it no longer traps errors, which might be a _really_ bad
idea???  Please note the comment about temp files - is it enough to
delete the three we create?

The code fragment above runs in a progress dialog.  Maybe I just never
tried it before, but I find that I cannot cancel the dialog.  Is
#waitForCompletion unfriendly to Dolphin's message loop?  If so, is
there a more forgiving way to get the same benefit?

Unfortunately, I do not have any example code that is likely to run on
just about any machine.  Quite the opposite, my examples are likely not
to run on all but two or three computers.  It might be useful to create
an example that pulls a text directory on the windows and system
directories, and then deliberately provides a nonsense path name or
something else to generate an error.  Comments or better ideas?

Again, feel free to ignore, distribute as-is, or alter this as you deem
appropriate.

Have a good one,

Bill


============

!ExternalProcess class methodsFor!

executeCommand:aStringCommand inDirectory:aDirectoryString
waitForSeconds:anIntegerSeconds out:outBlock error:errorBlock
        "Execute a command by launching a separate process.  outBlock and
errorBlock are
        monadic valuables, evaluated with the corresponding stream text from
the external
        process."

                | tmpStdinName tmpStdoutName tmpStderrName process startTemps endTemps
diffTemps |

        #wksSafe. "7-04 - second try at a helper method"
        startTemps := (File find: aDirectoryString, '\_*') collect: [
:aWin32FindData | aWin32FindData fileName ].

        tmpStdinName := File temporaryFilename.
        tmpStdoutName := File temporaryFilename.
        tmpStderrName := File temporaryFilename.

        process := ExternalProcess new
                                commandLine: aStringCommand;
                                directory: aDirectoryString;
                                secondsToWait: anIntegerSeconds;
                                stdinFilename: tmpStdinName;
                                stdoutFilename: tmpStdoutName;
                                stderrFilename: tmpStderrName;
                                yourself.

        [ process executeSync ] ensure:[
                ( Array with:tmpStdoutName with:tmpStderrName )
                        with:( Array with:outBlock with:errorBlock )
                        do:[ :fileName :block | | tmpFile |
                                tmpFile := FileStream read:fileName.
                                block value:tmpFile contents.
                                tmpFile close.
                        ].

                File delete:tmpStdinName.
                File delete:tmpStdoutName.
                File delete:tmpStderrName.

                "7-04 - are the explicit deletes above suffient?  If so, could
eliminate startTemps at the top."
                endTemps := (File find: aDirectoryString, '\_*') collect: [
:aWin32FindData | aWin32FindData fileName ].
                diffTemps := endTemps difference:startTemps.
                diffTemps do:[ :aFilename | File delete: aFilename ].
        ].
! !
!ExternalProcess class categoriesFor:
#executeCommand:inDirectory:waitForSeconds:out:error:!public! !



--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Launching other programs from within Smalltalk

Bob Jarvis-2
Bill,

Just saw this and haven't had time to really think about it.  Besides,
it's early...  :-)  I just posted an update to my Goodies so haven't
had time to get this integrated, but I'll try to make some time at
lunch today to look it over.  Thanks for your help and ideas!

Bob


Reply | Threaded
Open this post in threaded view
|

Re: Launching other programs from within Smalltalk

Bob Jarvis-3
In reply to this post by Schwab,Wilhelm K
I just put out a goodies update that includes this change.  I modified
what you gave me - I made it an instance method instead of a class
method and changed the message signature somewhat - but other than
changing things it's exactly the same.  :-)  Take a look and see what
you think.

Share and enjoy.

Bob


12