Consultor Eletrônico



Kbase 17450: How-to Run Windows Executables Synchronously
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   16/10/2008
Status: Unverified

GOAL:

How to run a Windows-based program Synchronously and have the Progress 4GL procedure execution wait until the Windows program execution has terminated

FACT(s) (Environment):

Windows
Progress 4GL
Progress 8.2x
Progress 9.x

FIX:

Using the external program interface to fire a Windows-based
executable with the Winexec API is a useful method for starting a process from the Progress 4GL. However execution of the Progress procedure will continue while the second process is running.

To run a Windows-based program Synchronously you can make two Windows API calls: CreateProcessA() and WaitForSingleObject() from the KERNEL32 library.

This example shows how to run a Windows executable synchronously.

/* Procedure to run Windows based executable synchronized */
DEFINE VARIABLE RProch AS INTEGER.
DEFINE VARIABLE RstartupCode AS INTEGER.

/* Define startupinfo structure */
DEFINE VARIABLE STARTUPINFO AS MEMPTR.
DEFINE VARIABLE cb AS INTEGER.
DEFINE VARIABLE lpReserved AS CHARACTER
FORMAT "X(8)" INITIAL " ".
DEFINE VARIABLE lpDesktop AS CHARACTER
FORMAT "X(8)" INITIAL " ".
DEFINE VARIABLE lpTitle AS CHARACTER
FORMAT "X(8)" INITIAL " ".
DEFINE VARIABLE ApplicationName AS INTEGER INITIAL 0.
DEFINE VARIABLE CommandLine AS CHARACTER
FORMAT "X(12)" INITIAL "NOTEPAD.EXE".
DEFINE VARIABLE ProcessAttributes AS INTEGER INITIAL 0.
DEFINE VARIABLE ThreadAttributes AS INTEGER INITIAL 0.
DEFINE VARIABLE InheritHandles AS INTEGER INITIAL 1.
DEFINE VARIABLE NORMAL_PRIORITY_CLASS AS INTEGER INITIAL 32.
DEFINE VARIABLE Environment AS INTEGER INITIAL 0.
DEFINE VARIABLE CurrentDirectory AS INTEGER INITIAL 0.

/* Define process information structure */
DEFINE VARIABLE PROCESS_INFORMATION AS MEMPTR.
DEFINE VARIABLE INFINITE AS INTEGER INITIAL -1.
DEFINE VARIABLE RprocCode AS INTEGER.

/* Set the size for the STARTUPINFO memory region */
SET-SIZE(STARTUPINFO) = 4
+ LENGTH(lpReserved) + 1
+ LENGTH(lpDesktop) + 1
+ LENGTH(lpTitle) + 1
+ 4
+ 4
+ 4
+ 4
+ 4
+ 4
+ 4
+ 4
+ 1
+ 1
+ 4
+ 4
+ 4.

/* Initialize the STARTUPINFO memory regions first location with
its' own size */
PUT-LONG(STARTUPINFO,1) = GET-SIZE(STARTUPINFO).

/* Set the size for the PROCESS_INFORMATION memory region */
SET-SIZE(PROCESS_INFORMATION)= 4 + 4 + 4 + 4.

/* Your code to be run before the external windows program
goes here */
MESSAGE "PROGRESS PROCEDURE RUNNING BEFORE SYNCH CALL"
VIEW-AS ALERT-BOX.

/* Time to run the Windows program.*/
/* Terminate the external program */
/* for 4GL execution to continue ! */
/* Create External process. */

RUN CreateProcessA(INPUT ApplicationName,
INPUT CommandLine,
INPUT ProcessAttributes,
INPUT ThreadAttributes,
INPUT InheritHandles,
INPUT NORMAL_PRIORITY_CLASS,
INPUT Environment,
INPUT CurrentDirectory,
INPUT STARTUPINFO,
INPUT-OUTPUT PROCESS_INFORMATION,
OUTPUT RstartupCode).

/* Run external process synchronously with process handle */
RUN WaitForSingleObject(INPUT GET-LONG(PROCESS_INFORMATION,1),
INPUT INFINITE,
OUTPUT RprocCode).

/* Windows-program execution terminated */
/* Release the Process handle */
RUN CloseHandle(INPUT GET-LONG(PROCESS_INFORMATION,1), OUTPUT RProch).

/* Continue your 4GL code here */
MESSAGE "PROGRESS PROCEDURE RUNNING AFTER SYNCH CALL"
VIEW-AS ALERT-BOX.

/* External procedure call definitions */
PROCEDURE CreateProcessA EXTERNAL "KERNEL32.DLL":
DEFINE INPUT PARAMETER lpApplicationName As Long.
DEFINE INPUT PARAMETER lpCommandLine AS CHARACTER
FORMAT "X(12)".
DEFINE INPUT PARAMETER lpProcessAttributes As Long.
DEFINE INPUT PARAMETER lpThreadAttributes As Long.
DEFINE INPUT PARAMETER bInheritHandles As Long.
DEFINE INPUT PARAMETER dwCreationFlags As Long.
DEFINE INPUT PARAMETER lpEnvironment As Long.
DEFINE INPUT PARAMETER lpCurrentDirectory As Long.
DEFINE INPUT PARAMETER lpStartupInfo As MEMPTR.
DEFINE INPUT-OUTPUT PARAMETER lpProcessInformation As MEMPTR.
DEFINE RETURN PARAMETER RstartupCode AS LONG.
END.

PROCEDURE W.aitForSingleObject EXTERNAL "KERNEL32.DLL":
DEFINE INPUT PARAMETER hHandle As Long.
DEFINE INPUT PARAMETER dwMilliseconds As Long.
DEFINE RETURN PARAMETER RprocCode AS long.
END.

PROCEDURE CloseHandle EXTERNAL "KERNEL32.DLL":
DEFINE INPUT PARAMETER hProcesshandle AS Long.
DEFINE RETURN PARAMETER retProcessh AS Long.
END..