What if you want to execute another program (process) from a GFA-BASIC 32 program? GB32 offers quite some commands and functions to do so. However, every new process is eventually started by calling the CreateProcess() API function. All those functions, including Windows API functions like ShellExecute(), WinExec() invoke the CreateProcess() API, which is declared as follows:
BOOL CreateProcess( LPCTSTR lpszImageName, // image file (.EXE) name LPCTSTR lpszCmdLine, // command line for new process LPSECURITY_ATTRIBUTES lpsaProcess, // how process will be shared LPSECURITY_ATTRIBUTES lpsaThread, // how new thread will be shared BOOL bInheritHandles, // TRUE to inherit handles DWORD fdwCreate, // creation flags LPVOID lpvEnvironment, // new environment (default = NULL) LPTSTR lpszCurrentDir, // name of new current directory LPSTARTUPINFO lpStartupInfo, // gives info about new process LPPROCESS_INFORMATION lpProcInfo ) // receives info about new process
WinExec - Command and Function
The CreateProcess function’s parameters permit precise control over the new process’s starting conditions. Because of these big number of parameters and options, some commands provide a simplified execution of CreateProcess. The WinExec() API already invokes CreateProcess with a lot of default values to create a detached process. WinExec() only expects lpszCmdLine and a show-window value for the STARTUPINFO.dwFlags member. All other values are set to zero or other default values. The new process is not a child process; after it is started there is no elation between the parent and the child process whatsoever.
WinExec() is a GB32 built-in API function, but it is not used. Instead GB32 uses its own WinExec function and it is defined as:
[Long =] WinExec(CmdLine$, CmdShow%)
The CmdLine$ is a null-terminated character string that contains the command line (file name plus optional parameters) for the application to be executed. WinExec passes parameters to the CreateProcess function in such a way that it is compatible to the 16-bits version of Windows. The return value is greater than 31 if the function succeeds. Otherwise it returns an error value
|0||The system is out of memory or resources.|
|ERROR_BAD_FORMAT (1)||The .exe file is invalid.|
|ERROR_FILE_NOT_FOUND (2)||The specified file was not found.|
|ERROR_PATH_NOT_FOUND(3)||The specified path was not found.|
The 32-bit WinExec() does not return an instance handle as the 16-bit WinExec() does. The return value can only be used to inspect an error value. Therefore, GB32 also defines a command variant: WinExec CmdLine$, CmdShow%.
Both versions - function and command - are linked to the same runtime function. Obviously, the return value can only be obtained with the function variant.
Exec – Command and Function
The WinExec takes two parameters, a command line argument and a show-window argument. Most of the times the second argument will be a default value of SW_SHOW or SW_SHOWNORMAL. The GB32 command Exec takes advantage of this behavior and allows the command-line parameter CmdLine$ to be split into a filename (path included) and options part. Although this might be useful for the developer, the command itself concatenates the parts before WinExec() API is invoked. The SW_SHOW is automatically used.
[Long =] Exec(file$, parameters$)
ShellExec – Command and Function
All processes are started using CreateProcess. It depends on the function which parameters are set and to what value. The GB32 ShellExec command/function invokes the ShellExecute() API, which sets and fills another set of CreateProcess’ arguments. Where the Exec and WinExec commands allow a simple start of a named exe program, the ShellExecute() function allows to start a process by a registered extension. Depending on the version used, ShellExec allows a more extended set of parameters for CreateProcess. In itself is ShellExec also a simplified form of invoking CreateProcess. See the help for more information on the parameters that can be used. For a comparison with WinExec and Exec we’ll only look at the variant that takes two parameters and performs exactly like these GB32 functions:
[Long = ] ShellExec file$ [, parameters$]
It doesn’t matter which GB32 command/function you use to spawn a new detached process. They all invoke the CreateProcess API. The return values of the function do not provide some handle to the new process, only an error value (if less than 32). Using Exec is tempting because it provides the easiest interface where the file and parameters are split.
GFA-BASIC 32 does provide a function that bypasses the above mentioned shortcuts to CreateProcess(): the System function/command. I will discuss this briefly in a next post.