call .exe file smalltalk

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

call .exe file smalltalk

Theo Pronk
Hi,

I would like to call "pkunzip.exe" with parameters, so it can unzip a
file for my application.

Does anyone have an example of calling an exe file with parameters from
Smalltalk ?

Thanks,
Theo


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

James Foster-3
ShellLibrary>>shellOpen: might be what you want.

"Theo Pronk" <[hidden email]> wrote in message
news:c3p2o7$29u2i8$[hidden email]...

> Hi,
>
> I would like to call "pkunzip.exe" with parameters, so it can unzip a
> file for my application.
>
> Does anyone have an example of calling an exe file with parameters from
> Smalltalk ?
>
> Thanks,
> Theo
>
>


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

Bob Jarvis-3
In reply to this post by Theo Pronk
Theo Pronk <[hidden email]> wrote in message news:<c3p2o7$29u2i8$[hidden email]>...
> Hi,
>
> I would like to call "pkunzip.exe" with parameters, so it can unzip a
> file for my application.
>
> Does anyone have an example of calling an exe file with parameters from
> Smalltalk ?

Try the ExternalProcess class in my goodies collection.

http://www.nls.net/mp/jarvis/Bob/DolphinGoodies.htm

I  hope this helps.


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

Christopher J. Demers
In reply to this post by Theo Pronk
"Theo Pronk" <[hidden email]> wrote in message
news:c3p2o7$29u2i8$[hidden email]...
> I would like to call "pkunzip.exe" with parameters, so it can unzip a
> file for my application.
>
> Does anyone have an example of calling an exe file with parameters from
> Smalltalk ?

I think Bob's package may be best for what you are actually doing.  However
for more generic use I use some variations on shellOpen:, see the methods I
added bellow.  I think it might be handy if something like the methods
bellow found their way into the base system.

The text between the bars can filed in and will add two methods to
ShellLibrary.
=======================
!ShellLibrary methodsFor!
shellOpen: fileString directory: dirString parameters: aParameter
"Opens the specified file, which can be an executable or document file.
Simplified wrapper around ShellExecute() to open a document."
| hInst |
hInst := self shellExecute: nil
lpOperation: 'open'
lpFile: fileString
lpParameters: aParameter
lpDirectory: dirString nShowCmd: SW_SHOWNORMAL.
^hInst asInteger <= 32
ifTrue: [self systemError]
ifFalse: [hInst]! !
!ShellLibrary categoriesFor: #shellOpen:directory:parameters:!public!win32
functions-shell library! !
!ShellLibrary methodsFor!
shellOpen: fileString parameters: aParameter
"Opens the specified file, which can be an executable or document file.
Simplified wrapper around ShellExecute() to open a document."
^self shellOpen: fileString directory: nil parameters: aParameter
! !
!ShellLibrary categoriesFor: #shellOpen:parameters:!must not
strip!public!win32 functions-shell library! !
=======================

Chris


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

David Simmons-2
Here is some generic S# code that gives you the Win32 sequences...

exec: cmdLine
inheritHandles: bInheritHandles

    <$lang=c++>
    bool doInherit = bInheritHandles != false_oop;
    STARTUPINFO startInfo;
    startInfo.cb = sizeof(startInfo);
    memset(&startInfo,0,sizeof(startInfo));
    PROCESS_INFORMATION processInfo;
    BOOL bOk = CreateProcess(
        (LPCTSTR)NULL,
        (LPTSTR)cmdLine->pBytes(),
        NULL,
        NULL,
        doInherit,
        (doInherit ? NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW),
        NULL,
        NULL,
        &startInfo,
        &processInfo
    );
    if (bOk)
        WaitForSingleObject(processInfo.hProcess,INFINITE);
    DWORD exitCode;
    GetExitCodeProcess(processInfo.hProcess, &exitCode);
    return AsNumber(exitCode);
-----------------
OR
-----------------
shellExec: commandLine verb: verb show: showFlags
   ^Shell32::ShellExecute(
        0, verb,
        commandLine,
        0, 0, showFlags).
-----------------
OR
If you need finer grain control, like monitoring state and capturing the
console (stdin/stdout/stderr) i/o in realtime as the spawned program runs...
-----------------
######################################################
# Copyright(c) Smallscript Corporation 1999-2004
#
# Environment:
#   AOS Framework Core Library and Services
#
# Author(s):
#   David Simmons [Portions(c) DAS 1987-2004]
######################################################
"""""""""""""""""""""""""""""""""""""""""
""  Services for spawning an executable
""  and capturing its console output.
"""""""""""""""""""""""""""""""""""""""""
""Project name: _ shared_fields:
Class ref.name: Public add.shared_fields:
                                alias[DWORD]    HANDLE,
                                alias[UInt16]   WORD,
                                alias[UInt32]   BOOL,
                                alias[UInt32]   LPVOID,
                                alias[DWORD]    LPBYTE.

Struct name: Standard.IO.SECURITY_ATTRIBUTES
    fields: auto struct DWORD   nLength,
                        LPVOID  lpSecurityDescriptor,
                        BOOL    bInheritHandle;
{
    Function [
        <::()>
    new
        ^__new() nLength(md_nsbytes)
    ]
}

Struct name: Standard.IO.STARTUPINFO
    fields: auto struct DWORD       cb,
                        LPTSTR      lpReserved,
                                    lpDesktop,
                                    lpTitle,
                        DWORD       dwX,
                                    dwY,
                                    dwXSize,
                                    dwYSize,
                                    dwXCountChars,
                                    dwYCountChars,
                                    dwFillAttribute,
                                    dwFlags,
                        WORD        wShowWindow,
                                    cbReserved2,
                        LPBYTE      lpReserved2,
                        HANDLE      hStdInput,
                                    hStdOutput,
                                    hStdError;
{
}

Struct name: Standard.IO.PROCESS_INFORMATION
    fields: auto struct HANDLE  hProcess,
                                hThread,
                        DWORD   dwProcessId,
                                dwThreadId;
{
}

Enum name: Standard.IO.K_IO
{
    //  These should already be somewhere
    #define MINCHAR     0x80
    #define MAXCHAR     0x7f
    #define MINSHORT    0x8000
    #define MAXSHORT    0x7fff
    #define MINLONG     0x80000000
    #define MAXLONG     0x7fffffff
    #define MAXBYTE     0xff
    #define MAXWORD     0xffff
    #define MAXDWORD    0xffffffff

    //  File IO Options
    #define FILE_TYPE_UNKNOWN   0x0000
    #define FILE_TYPE_DISK      0x0001
    #define FILE_TYPE_CHAR      0x0002
    #define FILE_TYPE_PIPE      0x0003
    #define FILE_TYPE_REMOTE    0x8000

    #define STD_INPUT_HANDLE    (-10)
    #define STD_OUTPUT_HANDLE   (-11)
    #define STD_ERROR_HANDLE    (-12)

    /////////////////
    //  Permissions
    /////////////////
    #define DELETE                                  (0x00010000L)
    #define READ_CONTROL                            (0x00020000L)
    #define WRITE_DAC                               (0x00040000L)
    #define WRITE_OWNER                             (0x00080000L)
    #define SYNCHRONIZE                             (0x00100000L)

    #define STANDARD_RIGHTS_REQUIRED                (0x000F0000L)

    #define STANDARD_RIGHTS_READ                    (READ_CONTROL)
    #define STANDARD_RIGHTS_WRITE                   (READ_CONTROL)
    #define STANDARD_RIGHTS_EXECUTE                 (READ_CONTROL)

    #define STANDARD_RIGHTS_ALL                     (0x001F0000L)

    #define SPECIFIC_RIGHTS_ALL                     (0x0000FFFFL)

    //
    // AccessSystemAcl access type
    //

    #define ACCESS_SYSTEM_SECURITY                  (0x01000000L)

    //
    // MaximumAllowed access type
    //

    #define MAXIMUM_ALLOWED                         (0x02000000L)

    //
    //  These are the generic rights.
    //

    #define GENERIC_READ                            (0x80000000L)
    #define GENERIC_WRITE                           (0x40000000L)
    #define GENERIC_EXECUTE                         (0x20000000L)
    #define GENERIC_ALL                             (0x10000000L)
    #define IO_REPARSE_TAG_MOUNT_POINT              (0xA0000003L)
    #define IO_REPARSE_TAG_HSM                      (0xC0000004L)
    #define IO_REPARSE_TAG_SIS                      (0x80000007L)
    #define IO_REPARSE_TAG_FILTER_MANAGER           (0x8000000BL)
    #define IO_COMPLETION_MODIFY_STATE              0x0002
    #define IO_COMPLETION_ALL_ACCESS
(STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
    #define DUPLICATE_CLOSE_SOURCE                  0x00000001
    #define DUPLICATE_SAME_ACCESS                   0x00000002

    ///////////////////////////
    //  CreateProcess Options
    ///////////////////////////
    #define STARTF_USESHOWWINDOW    0x00000001
    #define STARTF_USESIZE          0x00000002
    #define STARTF_USEPOSITION      0x00000004
    #define STARTF_USECOUNTCHARS    0x00000008
    #define STARTF_USEFILLATTRIBUTE 0x00000010
    #define STARTF_RUNFULLSCREEN    0x00000020  // ignored for non-x86
platforms
    #define STARTF_FORCEONFEEDBACK  0x00000040
    #define STARTF_FORCEOFFFEEDBACK 0x00000080
    #define STARTF_USESTDHANDLES    0x00000100
    //
    #define THREAD_BASE_PRIORITY_LOWRT  15      // value that gets a thread
to LowRealtime-1
    #define THREAD_BASE_PRIORITY_MAX    2       // maximum thread base
priority boost
    #define THREAD_BASE_PRIORITY_MIN    (-2)    // minimum thread base
priority boost
    #define THREAD_BASE_PRIORITY_IDLE   (-15)   // value that gets a thread
to idle
    //
    #define DEBUG_PROCESS                     0x00000001
    #define DEBUG_ONLY_THIS_PROCESS           0x00000002

    #define CREATE_SUSPENDED                  0x00000004

    #define DETACHED_PROCESS                  0x00000008

    #define CREATE_NEW_CONSOLE                0x00000010

    #define NORMAL_PRIORITY_CLASS             0x00000020
    #define IDLE_PRIORITY_CLASS               0x00000040
    #define HIGH_PRIORITY_CLASS               0x00000080
    #define REALTIME_PRIORITY_CLASS           0x00000100

    #define CREATE_NEW_PROCESS_GROUP          0x00000200
    #define CREATE_UNICODE_ENVIRONMENT        0x00000400

    #define CREATE_SEPARATE_WOW_VDM           0x00000800
    #define CREATE_SHARED_WOW_VDM             0x00001000
    #define CREATE_FORCEDOS                   0x00002000

    #define BELOW_NORMAL_PRIORITY_CLASS       0x00004000
    #define ABOVE_NORMAL_PRIORITY_CLASS       0x00008000
    #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000

    #define CREATE_BREAKAWAY_FROM_JOB         0x01000000
    #define CREATE_PRESERVE_CODE_AUTHZ_LEVEL  0x02000000

    #define CREATE_DEFAULT_ERROR_MODE         0x04000000
    #define CREATE_NO_WINDOW                  0x08000000

    #define PROFILE_USER                      0x10000000
    #define PROFILE_KERNEL                    0x20000000
    #define PROFILE_SERVER                    0x40000000

    #define CREATE_IGNORE_SYSTEM_DEFAULT      0x80000000

    #define THREAD_PRIORITY_LOWEST          THREAD_BASE_PRIORITY_MIN
    #define THREAD_PRIORITY_BELOW_NORMAL    (THREAD_PRIORITY_LOWEST+1)
    #define THREAD_PRIORITY_NORMAL          0
    #define THREAD_PRIORITY_HIGHEST         THREAD_BASE_PRIORITY_MAX
    #define THREAD_PRIORITY_ABOVE_NORMAL    (THREAD_PRIORITY_HIGHEST-1)
    #define THREAD_PRIORITY_ERROR_RETURN    (MAXLONG)

    #define THREAD_PRIORITY_TIME_CRITICAL   THREAD_BASE_PRIORITY_LOWRT
    #define THREAD_PRIORITY_IDLE            THREAD_BASE_PRIORITY_IDLE

    //////////////////////////////////
    //
    //////////////////////////////////
    #define STATUS_WAIT_0                    (0x00000000L)
    #define STATUS_ABANDONED_WAIT_0          (0x00000080L)
    #define STATUS_USER_APC                  (0x000000C0L)
    #define STATUS_TIMEOUT                   (0x00000102L)
    #define STATUS_PENDING                   (0x00000103L)
    #define DBG_EXCEPTION_HANDLED            (0x00010001L)
    #define DBG_CONTINUE                     (0x00010002L)
    #define STATUS_SEGMENT_NOTIFICATION      (0x40000005L)
    #define DBG_TERMINATE_THREAD             (0x40010003L)
    #define DBG_TERMINATE_PROCESS            (0x40010004L)
    #define DBG_CONTROL_C                    (0x40010005L)
    #define DBG_CONTROL_BREAK                (0x40010008L)
    #define STATUS_GUARD_PAGE_VIOLATION      (0x80000001L)
    #define STATUS_DATATYPE_MISALIGNMENT     (0x80000002L)
    #define STATUS_BREAKPOINT                (0x80000003L)
    #define STATUS_SINGLE_STEP               (0x80000004L)
    #define DBG_EXCEPTION_NOT_HANDLED        (0x80010001L)
    #define STATUS_ACCESS_VIOLATION          (0xC0000005L)
    #define STATUS_IN_PAGE_ERROR             (0xC0000006L)
    #define STATUS_INVALID_HANDLE            (0xC0000008L)
    #define STATUS_NO_MEMORY                 (0xC0000017L)
    #define STATUS_ILLEGAL_INSTRUCTION       (0xC000001DL)
    #define STATUS_NONCONTINUABLE_EXCEPTION  (0xC0000025L)
    #define STATUS_INVALID_DISPOSITION       (0xC0000026L)
    #define STATUS_ARRAY_BOUNDS_EXCEEDED     (0xC000008CL)
    #define STATUS_FLOAT_DENORMAL_OPERAND    (0xC000008DL)
    #define STATUS_FLOAT_DIVIDE_BY_ZERO      (0xC000008EL)
    #define STATUS_FLOAT_INEXACT_RESULT      (0xC000008FL)
    #define STATUS_FLOAT_INVALID_OPERATION   (0xC0000090L)
    #define STATUS_FLOAT_OVERFLOW            (0xC0000091L)
    #define STATUS_FLOAT_STACK_CHECK         (0xC0000092L)
    #define STATUS_FLOAT_UNDERFLOW           (0xC0000093L)
    #define STATUS_INTEGER_DIVIDE_BY_ZERO    (0xC0000094L)
    #define STATUS_INTEGER_OVERFLOW          (0xC0000095L)
    #define STATUS_PRIVILEGED_INSTRUCTION    (0xC0000096L)
    #define STATUS_STACK_OVERFLOW            (0xC00000FDL)
    #define STATUS_CONTROL_C_EXIT            (0xC000013AL)
    #define STATUS_FLOAT_MULTIPLE_FAULTS     (0xC00002B4L)
    #define STATUS_FLOAT_MULTIPLE_TRAPS      (0xC00002B5L)
    #define STATUS_REG_NAT_CONSUMPTION       (0xC00002C9L)
    #define STATUS_SXS_EARLY_DEACTIVATION    (0xC015000FL)
    #define STATUS_SXS_INVALID_DEACTIVATION  (0xC0150010L)
    //
    //////////
    //
    #define INVALID_HANDLE_VALUE                (-1)
    #define INVALID_FILE_SIZE                   (0xFFFFFFFF)
    #define INVALID_SET_FILE_POINTER            (-1)
    #define INVALID_FILE_ATTRIBUTES             (-1)

    #define FILE_BEGIN           0
    #define FILE_CURRENT         1
    #define FILE_END             2

    #define TIME_ZONE_ID_INVALID                (0xFFFFFFFF)

    #define WAIT_FAILED                         (0xFFFFFFFF)
    #define WAIT_OBJECT_0                       ((STATUS_WAIT_0 ) + 0 )

    #define WAIT_ABANDONED                      ((STATUS_ABANDONED_WAIT_0 )
+ 0 )
    #define WAIT_ABANDONED_0                    ((STATUS_ABANDONED_WAIT_0 )
+ 0 )

    #define WAIT_TIMEOUT                        258L    // dderror

    #define WAIT_IO_COMPLETION                  STATUS_USER_APC
    #define STILL_ACTIVE                        STATUS_PENDING
    #define EXCEPTION_ACCESS_VIOLATION          STATUS_ACCESS_VIOLATION
    #define EXCEPTION_DATATYPE_MISALIGNMENT     STATUS_DATATYPE_MISALIGNMENT
    #define EXCEPTION_BREAKPOINT                STATUS_BREAKPOINT
    #define EXCEPTION_SINGLE_STEP               STATUS_SINGLE_STEP
    #define EXCEPTION_ARRAY_BOUNDS_EXCEEDED     STATUS_ARRAY_BOUNDS_EXCEEDED
    #define EXCEPTION_FLT_DENORMAL_OPERAND
STATUS_FLOAT_DENORMAL_OPERAND
    #define EXCEPTION_FLT_DIVIDE_BY_ZERO        STATUS_FLOAT_DIVIDE_BY_ZERO
    #define EXCEPTION_FLT_INEXACT_RESULT        STATUS_FLOAT_INEXACT_RESULT
    #define EXCEPTION_FLT_INVALID_OPERATION
STATUS_FLOAT_INVALID_OPERATION
    #define EXCEPTION_FLT_OVERFLOW              STATUS_FLOAT_OVERFLOW
    #define EXCEPTION_FLT_STACK_CHECK           STATUS_FLOAT_STACK_CHECK
    #define EXCEPTION_FLT_UNDERFLOW             STATUS_FLOAT_UNDERFLOW
    #define EXCEPTION_INT_DIVIDE_BY_ZERO
STATUS_INTEGER_DIVIDE_BY_ZERO
    #define EXCEPTION_INT_OVERFLOW              STATUS_INTEGER_OVERFLOW
    #define EXCEPTION_PRIV_INSTRUCTION
STATUS_PRIVILEGED_INSTRUCTION
    #define EXCEPTION_IN_PAGE_ERROR             STATUS_IN_PAGE_ERROR
    #define EXCEPTION_ILLEGAL_INSTRUCTION       STATUS_ILLEGAL_INSTRUCTION
    #define EXCEPTION_NONCONTINUABLE_EXCEPTION
STATUS_NONCONTINUABLE_EXCEPTION
    #define EXCEPTION_STACK_OVERFLOW            STATUS_STACK_OVERFLOW
    #define EXCEPTION_INVALID_DISPOSITION       STATUS_INVALID_DISPOSITION
    #define EXCEPTION_GUARD_PAGE                STATUS_GUARD_PAGE_VIOLATION
    #define EXCEPTION_INVALID_HANDLE            STATUS_INVALID_HANDLE
    #define CONTROL_C_EXIT                      STATUS_CONTROL_C_EXIT
}

Class name: Standard.Environment.Spawn imports: Standard.IO.K_IO,
KGUICore_A, Kernel32, User32
    fields: auto                    appName,
                                    cmdLine,
                                    clientCallback,
                                    procInfo, startInfo,
                                    hStdinReadPipe, hStdinWritePipe,
                                    hStdoutReadPipe, hStdoutWritePipe,
                                    hStderrReadPipe, hStderrWritePipe,
                                    hSaveStdin, hSaveStdout, hSaveStderr;
            auto virtual[procInfo]  hProcess,
                 virtual[procInfo]  hThread,
                 virtual[procInfo]  dwThreadId,
                 virtual[procInfo]  dwProcessId;
{
    Function [
    ExecAndCaptureOutput(cmd, <[out]> captured_data)
        captured_data := nil.
        |buffer := String(2048)||progressHandler| :=
        [:spawn :dwExitCode||lpTotalBytesAvail|
            PeekNamedPipe(spawn.hStdoutReadPipe, null, 0, null,
&lpTotalBytesAvail, null).
            while(lpTotalBytesAvail)
            [
                |nToRead| := lpTotalBytesAvail min: buffer.size.
                ReadFile(spawn.hStdoutReadPipe, buffer, nToRead, &nToRead,
null).
                lpTotalBytesAvail :-= nToRead.
                captured_data :+= buffer[1:nToRead].
            ].
        ].
        return ExecCmd(cmd, progressHandler).
    ]
    Function [<::execCmd(<>,<>)>
    ExecCmd(cmdLine, clientCallback)
        ""  Note that we could provide a variant the
        ""  separated the target-exe from its arguments.
        ""  See OS docs on CreateProcess.
        ^__new() cmdLine(cmdLine); clientCallback(clientCallback); execute.
    ]
    Function [<::execCmd(<>,<>,<>)>
    ExecCmd(appName, cmdLine, clientCallback)
        ""  Note that we could provide a variant the
        ""  separated the target-exe from its arguments.
        ""  See OS docs on CreateProcess.
        ^__new() appName(appName); cmdLine(cmdLine);
clientCallback(clientCallback); execute.
    ]

    Method [
    redirectIO
        "" Preflight stdxxx pipe creation
        |hStdoutReadPipeTmp, hPipe, lpPipeAttributes :=
SECURITY_ATTRIBUTES()|

        "" Set the bInheritHandle flag so pipe handles are inherited.
        lpPipeAttributes.bInheritHandle := true.

        """""""""""""""""""""""""""""
        "" Allocate the STDOUT pipe
        """""""""""""""""""""""""""""
        if(!CreatePipe(&hStdoutReadPipeTmp, &hPipe, lpPipeAttributes, null
"use default pipe size"))
   throw('CreatePipe failed').
        hStdoutWritePipe := hPipe.

  "" Set a write handle to the pipe to be STDOUT.
  if (!SetStdHandle(STD_OUTPUT_HANDLE, hStdoutWritePipe))
   throw('Redirecting STDOUT failed').

  "" Create noninheritable read handle and close the inheritable read
handle.
  if (!DuplicateHandle(GetCurrentProcess(), hStdoutReadPipeTmp,
                    GetCurrentProcess(), &hPipe,
                    0, false, DUPLICATE_SAME_ACCESS))
   throw('DuplicateHandle failed').
        hStdoutReadPipe := hPipe.
        CloseHandle(hStdoutReadPipeTmp).

  """"""""""""""""""""""""""""
  "" Allocate the STDERR pipe
  """"""""""""""""""""""""""""
        |hStderrReadPipeTmp|
  if (!CreatePipe(&hStderrReadPipeTmp, &hPipe, lpPipeAttributes, null))
   throw('Stderr pipe creation failed').
        hStderrWritePipe := hPipe.

  "" Set a write handle to the pipe to be STDERR.
  if (!SetStdHandle(STD_ERROR_HANDLE, hStderrWritePipe))
   throw('Redirecting Stderr failed').

  "" Create noninheritable read handle and close the inheritable read
handle.
  if (!DuplicateHandle(GetCurrentProcess(), hStderrReadPipeTmp,
                    GetCurrentProcess(), &hPipe,
                    0, false, DUPLICATE_SAME_ACCESS))
   throw('DuplicateHandle failed').
        hStderrReadPipe := hPipe.
        CloseHandle(hStderrReadPipeTmp).

  """"""""""""""""""""""""""""
  "" Allocate the STDIN pipe
  """"""""""""""""""""""""""""
        |hStdinWritePipeTmp|
  if (!CreatePipe(&hPipe, &hStdinWritePipeTmp, lpPipeAttributes, null))
   throw('Stdin pipe creation failed').
        hStdinReadPipe := hPipe.

  "" Set a read handle to the pipe to be STDIN.
  if (!SetStdHandle(STD_INPUT_HANDLE, hStdinReadPipe))
   throw('Redirecting Stdin failed').

  "" Duplicate the write handle to the pipe so it is not inherited.
  if (!DuplicateHandle(GetCurrentProcess(), hStdinWritePipeTmp,
                    GetCurrentProcess(), &hPipe,
                    0, false, DUPLICATE_SAME_ACCESS))
   throw('DuplicateHandle failed').
        hStdinWritePipe := hPipe.
        CloseHandle(hStdinWritePipeTmp).
    ]

    Method [
    createChildProcess
     "" Set up members of STARTUPINFO structure.
        startInfo := STARTUPINFO().
     startInfo.dwFlags := STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW.
     startInfo.wShowWindow := SW_HIDE.
     startInfo.hStdInput := hStdinReadPipe.
     startInfo.hStdOutput := hStdoutWritePipe.
     startInfo.hStdError := hStdoutWritePipe.

        procInfo := PROCESS_INFORMATION().

        "" Tweak as needed for various CreateProcess quirks
        unless.nil(appName)
        [
            "" Unquote the appName, as required
            if(appName[1] == $")"""
                appName := appName[2:appName.lastIndexOf($")-1]. """

            "" Ensure spacing for when it concatenates them
            if (cmdLine.size and: [cmdLine[1].isWhitespace.not])
                cmdLine := ' '+cmdLine.
        ].

     "" Create the child process.
        ^CreateProcess(appName,     "" application name
      cmdLine,              "" command line (or appName+' '+cmdLine)
      null,               "" process security attributes
      null,               "" primary thread security attributes
      true,               "" handles are inherited
      CREATE_NEW_CONSOLE,     "" creation flags
      null,               "" use parent's environment
      null,               "" use parent's current directory
      startInfo,              "" STARTUPINFO pointer
      &procInfo).             "" receives PROCESS_INFORMATION
    ]

    Method [
    execute
        "" Save the STDXXX handles.
        hSaveStdin := GetStdHandle(STD_INPUT_HANDLE).
        hSaveStderr := GetStdHandle(STD_ERROR_HANDLE).
        hSaveStdout := GetStdHandle(STD_OUTPUT_HANDLE).

        try
        [
         "" Now create the child process.
            redirectIO().
         if (createChildProcess() != true) [
                |error| := thread.lastHostErrorString.
                if.nil(|request| := appName)
                    request := cmdLine.
                else unless.nil(cmdLine)
                    request :+= "follow its spacing rules" cmdLine.
          throw('Create process failed : '
                    + error + ' : exec(`'' + request + '`')').
            ].
        ]
        finally [
         "" After process creation, restore the saved STDXXX handles.
            SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout).
            SetStdHandle(STD_ERROR_HANDLE, hSaveStderr).
         SetStdHandle(STD_INPUT_HANDLE, hSaveStdin).
        ].

        |
            dwExitCode, handles := ByteArray(12),
            dwTimeoutMS := 100, dwWakeMask := QS_ALLEVENTS,
            dwFlags := (MWMO_ALERTABLE | (VM.IsWinNT4 ?: 0 :
MWMO_INPUTAVAILABLE))
        |
        try [
            "" Check process status, if exited we must break out of our loop
            |nHandles := handles.size // 4|
            handles
    uint32At: 8 put: hStderrWritePipe;
    uint32At: 4 put: hStdoutWritePipe;
    uint32At: 0 put: hProcess.
            while(hProcess and: [GetExitCodeProcess(hProcess, &dwExitCode)
and: [dwExitCode = STILL_ACTIVE]])
            [
                "" invoke clientCallback
                clientCallback.(self, dwExitCode).

                "" Block waiting for IO, processExit, or timeout
                |iErr| := MsgWaitForMultipleObjectsEx(
                    nHandles, handles, dwTimeoutMS,
                    dwWakeMask, dwFlags
                ).

                "" Give up a slice before we do something again
                if (iErr = WAIT_FAILED) SleepEx(0, false).
            ].

            "" invoke clientCallback
            clientCallback.(self, dwExitCode).
        ]
        finally [
            "" Close/release the temporary pipes
            CloseHandle(hStdinReadPipe).
            CloseHandle(hStdinWritePipe).
            CloseHandle(hStdoutReadPipe).
            CloseHandle(hStdoutWritePipe).
            CloseHandle(hStderrReadPipe).
            CloseHandle(hStderrWritePipe).
        ].

        "" Return the exit code
       ^dwExitCode.
    ]
}

-- Dave S. [www.smallscript.org]

"Christopher J. Demers" <[hidden email]> wrote in
message news:c3q9ra$2ahof9$[hidden email]...
> "Theo Pronk" <[hidden email]> wrote in message
> news:c3p2o7$29u2i8$[hidden email]...
> > I would like to call "pkunzip.exe" with parameters, so it can unzip a
> > file for my application.
> >
> > Does anyone have an example of calling an exe file with parameters from
> > Smalltalk ?
>
> I think Bob's package may be best for what you are actually doing.
However
> for more generic use I use some variations on shellOpen:, see the methods
I

> added bellow.  I think it might be handy if something like the methods
> bellow found their way into the base system.
>
> The text between the bars can filed in and will add two methods to
> ShellLibrary.
> =======================
> !ShellLibrary methodsFor!
> shellOpen: fileString directory: dirString parameters: aParameter
> "Opens the specified file, which can be an executable or document file.
> Simplified wrapper around ShellExecute() to open a document."
> | hInst |
> hInst := self shellExecute: nil
> lpOperation: 'open'
> lpFile: fileString
> lpParameters: aParameter
> lpDirectory: dirString nShowCmd: SW_SHOWNORMAL.
> ^hInst asInteger <= 32
> ifTrue: [self systemError]
> ifFalse: [hInst]! !
> !ShellLibrary categoriesFor: #shellOpen:directory:parameters:!public!win32
> functions-shell library! !
> !ShellLibrary methodsFor!
> shellOpen: fileString parameters: aParameter
> "Opens the specified file, which can be an executable or document file.
> Simplified wrapper around ShellExecute() to open a document."
> ^self shellOpen: fileString directory: nil parameters: aParameter
> ! !
> !ShellLibrary categoriesFor: #shellOpen:parameters:!must not
> strip!public!win32 functions-shell library! !
> =======================
>
> Chris
>
>


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

David Simmons-2
In reply to this post by Christopher J. Demers
Here is an example of calling the previously provided code:

    |cmds| := String().Write('xcopy /D /K /X /Y "{0}" "{1}"', f1.trim,
f2.trim).
    thisThread.exec: cmds inheritHandles: true.

-- Dave S. [www.smallscript.org]

"Christopher J. Demers" <[hidden email]> wrote in
message news:c3q9ra$2ahof9$[hidden email]...
> "Theo Pronk" <[hidden email]> wrote in message
> news:c3p2o7$29u2i8$[hidden email]...
> > I would like to call "pkunzip.exe" with parameters, so it can unzip a
> > file for my application.
> >
> > Does anyone have an example of calling an exe file with parameters from
> > Smalltalk ?
>
> I think Bob's package may be best for what you are actually doing.
However
> for more generic use I use some variations on shellOpen:, see the methods
I

> added bellow.  I think it might be handy if something like the methods
> bellow found their way into the base system.
>
> The text between the bars can filed in and will add two methods to
> ShellLibrary.
> =======================
> !ShellLibrary methodsFor!
> shellOpen: fileString directory: dirString parameters: aParameter
> "Opens the specified file, which can be an executable or document file.
> Simplified wrapper around ShellExecute() to open a document."
> | hInst |
> hInst := self shellExecute: nil
> lpOperation: 'open'
> lpFile: fileString
> lpParameters: aParameter
> lpDirectory: dirString nShowCmd: SW_SHOWNORMAL.
> ^hInst asInteger <= 32
> ifTrue: [self systemError]
> ifFalse: [hInst]! !
> !ShellLibrary categoriesFor: #shellOpen:directory:parameters:!public!win32
> functions-shell library! !
> !ShellLibrary methodsFor!
> shellOpen: fileString parameters: aParameter
> "Opens the specified file, which can be an executable or document file.
> Simplified wrapper around ShellExecute() to open a document."
> ^self shellOpen: fileString directory: nil parameters: aParameter
> ! !
> !ShellLibrary categoriesFor: #shellOpen:parameters:!must not
> strip!public!win32 functions-shell library! !
> =======================
>
> Chris
>
>


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

Blair McGlashan
In reply to this post by David Simmons-2
"David Simmons" <[hidden email]> wrote in message
news:[hidden email]...
> Here is some generic S# code that gives you the Win32 sequences...
>
> exec: cmdLine
> inheritHandles: bInheritHandles
> [... ~550 lines snipped...]

Thanks David, but I think Chris Demer's solution will be adequate. Failing
that Bob Jarvis' package provides the necessary level of control for more
complex requirements.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: call .exe file smalltalk

Theo Pronk
In reply to this post by Christopher J. Demers
Thanks Chris,

The methods you gave helped greatly, after I discovered that
ShellLibrary requires "default" not "new"

eg to run pkunzip from c:\tools\pkzip with parameter /h I had to do the
following:

ShellLibrary default shellOpen: 'pkunzip.exe' directory:
'C:/Tools/pkzip/' parameters: '/h'

Regards,
Theo
PS Bob your ExternalProcess.pac also like a looks addition in the furture.
============================



Christopher J. Demers wrote:

> "Theo Pronk" <[hidden email]> wrote in message
> news:c3p2o7$29u2i8$[hidden email]...
>
>>I would like to call "pkunzip.exe" with parameters, so it can unzip a
>>file for my application.
>>
>>Does anyone have an example of calling an exe file with parameters from
>>Smalltalk ?
>
>
> I think Bob's package may be best for what you are actually doing.  However
> for more generic use I use some variations on shellOpen:, see the methods I
> added bellow.  I think it might be handy if something like the methods
> bellow found their way into the base system.
>
> The text between the bars can filed in and will add two methods to
> ShellLibrary.
> =======================
> !ShellLibrary methodsFor!
> shellOpen: fileString directory: dirString parameters: aParameter
> "Opens the specified file, which can be an executable or document file.
> Simplified wrapper around ShellExecute() to open a document."
> | hInst |
> hInst := self shellExecute: nil
> lpOperation: 'open'
> lpFile: fileString
> lpParameters: aParameter
> lpDirectory: dirString nShowCmd: SW_SHOWNORMAL.
> ^hInst asInteger <= 32
> ifTrue: [self systemError]
> ifFalse: [hInst]! !
> !ShellLibrary categoriesFor: #shellOpen:directory:parameters:!public!win32
> functions-shell library! !
> !ShellLibrary methodsFor!
> shellOpen: fileString parameters: aParameter
> "Opens the specified file, which can be an executable or document file.
> Simplified wrapper around ShellExecute() to open a document."
> ^self shellOpen: fileString directory: nil parameters: aParameter
> ! !
> !ShellLibrary categoriesFor: #shellOpen:parameters:!must not
> strip!public!win32 functions-shell library! !
> =======================
>
> Chris
>
>