DOCUMENT:Q89132 07-NOV-1999 [fortran] TITLE :How to Run a Program from Within a QuickWin Program PRODUCT :Microsoft Fortran Compiler PROD/VER::5.1 OPER/SYS: KEYWORDS: ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft FORTRAN for Windows, version 5.1 ------------------------------------------------------------------------------- Microsoft FORTRAN version 5.1 QuickWin programs can spawn other programs while running under Windows by using the Windows API function WinExec(). The spawned programs can be MS-DOS- or Windows-based applications. Because Windows is a multitasking system, the spawning program may terminate before the spawned programs finish their task. It is possible to wait for termination of a spawned process by using the GetModuleUsage() Windows API function. WinExec() can also be used to emulate the system() function by spawning MS-DOS COMMAND.COM. It is recommended to use a program information file (PIF) when spawning any MS-DOS executable such as COMMAND.COM. MORE INFORMATION ================ WinExec() returns an integer value greater than 32 if successful. If unsuccessful, it returns of the following codes: 0 - The system was out of memory, or the executable file was corrupt, or relocations were invalid. 2 - The file was not found. 3 - The path was not found. 5 - An attempt was made to dynamically link to a task, or there was a sharing or network protection error. 6 - The library required separate data segments for each task. 10 - The Windows version was incorrect. 11 - The executable file was invalid. It was either not a Windows-based application or there was an error in the .EXE image. 12 - The application was designed for OS/2. 13 - The application was designed for MS-DOS 4.0. 14 - The type of executable file was unknown. 15 - An attempt was made to load a real-mode application (developed for an earlier version of Windows). 16 - An attempt was made to load a second instance of an executable file containing multiple data segments that were not marked "read-only." 17 - Attempt in large-frame EMS mode to load a second instance of an application that links to certain non-shareable DLLs already in use. 18 - Attempt in real mode to load an application marked for protected mode only. Under Windows 3.1 the WinExec() function may also return the following codes: 8 - There was insufficient memory to start the application. 19 - An attempt was made to load a compressed executable file. The file must be expanded before it can be loaded. 20 - The DLL file was invalid. One of the DLLs required to run this application was corrupt. 21 - The application requires Microsoft Windows 32-bit extensions. Also note that under Windows, 3.1 the return codes 17 and 18 have been eliminated. WinExec() may be unsuccessful if the QuickWin program tries to run an MS-DOS application directly. If the file to be run is a non-Windows file, you should create a program information file (PIF) to run it. For information about PIFs and how to create them, see the "Microsoft Windows User's Guide" for version 3.1. The syntax of WinExec() is as follows: INTERFACE TO INTEGER*2 FUNCTION WinExec [PASCAL] + (lpCmdLine, nCmdShow) CHARACTER*1 lpCmdLine [REFERENCE] INTEGER*2 nCmdShow [VALUE] END The first argument, lpCmdLine, is the command line required to run the file. This must be a NULL terminated string, which may also contain command-line arguments for the program. If a path is not specified, WinExec() will look in the following directories: the working directory of the calling program, the WINDOWS directory, and finally in the WINDOWS\SYSTEM directory. If the program is a non-Windows .EXE, the PIF indicates the directory where it is located. The second argument, nCmdShow, indicates the initial state of the application's main window when it is created. This parameter can be one of the following numbers: 1 Start the application in a normal size window. 2 Start the application minimized. Show an icon at the bottom of the screen. 3 Start the application in a maximized window. 4 Start the application but set the focus back to the calling program. 7 Start the application minimized and set the focus back to the calling program. If the nCmdShow option is set so that the spawned MS-DOS process does not retain the focus, it is imperative to create a PIF for the process that allows background processing. Otherwise, the MS-DOS process will start then suspend its processing, and the main program will also be suspended indefinitely waiting for the MS-DOS process to terminate. GetModuleUsage() returns the reference count of the module if the function is successful, and a zero if no instances of the module are found. The syntax of GetModuleUsage() is as follows INTERFACE TO INTEGER*2 FUNCTION GetModuleUsage [PASCAL] + (hinst) INTEGER*2 hinst [value] END where hinst identifies the module or an instance of the module. Sample Code 1 ------------- The following code demonstrates how to use the WinExec() and GetModuleUsage() APIs from within a FORTRAN program. This code should be compiled and linked as a QuickWin Windows program. Note that the compiler option /MW0 is recommended to avoid having to access the YIELDQQ subroutine as a function. The program first executes a simple QuickWin program, then it calls COMMAND.COM to redirect a directory listing into a file. Finally, it calls a FORTRAN MS-DOS application. MAINPROG.FOR INTERFACE TO INTEGER*2 FUNCTION WinExec [PASCAL] + (lpCmdLine, nCmdShow) CHARACTER*1 lpCmdLine [REFERENCE] INTEGER*2 nCmdShow [VALUE] END INTERFACE TO INTEGER*2 FUNCTION GetModuleUsage [PASCAL] + (hinst) INTEGER*2 hinst [value] END INTERFACE TO INTEGER*2 FUNCTION WinExecPause + (progname, style) CHARACTER*(*) progname !C string INTEGER*2 style END PROGRAM Sample_WINEXEC_API integer*2 WinExecPause, ihandle character*20 progname progname = 'subprog1'c ihandle = WinExecPause(progname, 1) ! Start in normal mode !Emulate DOS's system call. !Use the dosprmpt PIF file. ihandle = WinExecPause('dosprmpt.pif /c dir>dir.dat'C, 1) progname = 'subprog2'c ihandle = WinExecPause(progname, 1) print*, 'Main Program terminated' end !End of Main() C WinExecPause is a wrapper function for the WinExec function. integer*2 function WinExecPause(progname, style) character*(*) progname !C string integer*2 style integer*2 WinExec, GetModuleUsage WinExecPause = WinExec(progname, style) if (WinExecPause .LE. 32) then print *, 'Unable to run ',progname return endif do while (GetModuleUsage(WinExecPause)) ! Wait call YIELDQQ() end do end !End of WinExecPause Sample Code 2 ------------- The following is the code for SUBPROG1.FOR, a small QuickWin program that will be spawned from the main QuickWin program: SUBPROG1.FOR PRINT *, 'Inside Exe 1 Program...hit ENTER to continue.' READ (*, *) END Sample Code 3 ------------- Here is the code for SUBPROG2.FOR, a small MS-DOS program spawned from the main QuickWin program: SUBPROG2.FOR PRINT *, 'Inside Exe 2 Program...hit ENTER to continue.' READ (*, *) END Project Makefile ---------------- # Note that the file FL.DEF from the FORTRAN\BINB directory # will have to be copied into the same directory as the # source code. ALL : MainProg.EXE SubProg1.EXE SubProg2.EXE MainProg.EXE : MainProg.OBJ Link MainProg.OBJ, , NUL, /NOD LLIBFEW, FL.DEF SubProg1.EXE : SubProg1.OBJ Link SubProg1.OBJ, , NUL, /NOD LLIBFEW, FL.DEF SubProg2.EXE : SubProg2.OBJ Link SubProg2.OBJ; MainProg.OBJ : MainProg.FOR FL /MW0 /c MainProg.FOR SubProg1.OBJ : SubProg1.FOR FL /MW /c SubProg1.FOR SubProg2.OBJ : SubProg2.FOR FL /c SubProg2.FOR Additional query words: kbinf 5.10 ====================================================================== Keywords : Technology : kbAudDeveloper kbFortranSearch kbFORTRAN510QuickWin Version : :5.1 ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 1999.