KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q89132: How to Run a Program from Within a QuickWin Program

Article: Q89132
Product(s): Microsoft Fortran Compiler
Version(s): 5.1
Operating System(s): 
Keyword(s): 
Last Modified: 07-NOV-1999

-------------------------------------------------------------------------------
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 1986-2002.