Run a program from within a program

  
Match 

  •                  
  •                  
  •                 word(s).
  • If you have any questions or comments,
    please visit us on the Forums

    FAQ > How do I... (Level 2) > Run a program from within a program

    This item was added on: 2003/02/07

    There are various ways to run another program from within your own. Most of the good ones are compiler dependant, so best research your help files before going too far 

    In all the example code below you'll find some sample output. In the cases where a child program has been invoked, this source was used to make that child:

    #include <stdio.h> 
    
    int main(int argc, char *argv[] )
    {
      int i = 0;
      printf("I am the child\n");
      while (--argc)
        printf ("Arg %d %s\n", ++i, *++argv);
      return 0;
    }
    
    

    Now, we'll start with a simple example of system().

    OPTION 1 - system()

    Prototype:
    int system (const char * s);

    This function executes a command specified in s, and returns after the command has been completed. A few reasons not to use this method are:

    • The child program is uninterruptible from the parent program. This means that you cannot stop the program you have started. If it takes 5 hours to complete, that's how long your program will wait 
    • You cannot communicate or share variables with the child process
    • For various security reasons, its unsafe and may leave your system open to exploitation.
    • In system terms, its relatively slow.

      Having said that, it is easy to use, and these things have their place. Here is a example of how to use it.

      /*
       * This example assumes the program you want to execute
       * is called child.exe, and resides in the same 
       * directory as this program
       */
      
      #include <stdlib.h> 
      #include <stdio.h> 
      #include <string.h> 
      
      int main()
      {
        char child1[] = "child.exe";
        char child2[BUFSIZ];
        
        /* 
         * Execute by passing the name directly 
         */
        system ("child.exe");
        
        /*
         * Execute by passing an array name
         */
        system (child1);
        
        /*
         * Build a buffer, and execute the commands within it
         */
        strcpy (child2, "child.exe");
        strcat (child2, " -aparm -b");
        
        printf ("Executing %s\n", child2);
        system (child2);
        
        return 0;
      }
      
      /*
       * Program output:
       I am the child
       I am the child
       Executing child.exe -aparm -b
       I am the child
       Arg 1 -aparm
       Arg 2 -b
       *
       */
      
      

      OPTION 2 - spawn

      There a family of functions collectively known as spawn. These are:

      #include <process.h>
      int spawnl(   mode, path, arg0, arg1..., argn, 
                    NULL );
      int spawnle(  mode, path, arg0, arg1..., argn, 
                    NULL, envp);
      int spawnlp(  mode, file, arg0, arg1..., argn, 
                    NULL );
      int spawnlpe( mode, file, arg0, arg1..., argn, 
                    NULL, envp);
      int spawnv(   mode, path, argv );
      int spawnve(  mode, path, argv, envp );
      int spawnvp(  mode, file, argv );
      int spawnvpe( mode, file, argv, envp );
      
      int         mode;      /* mode for parent      */
      const char *path;      /* file name incl. path */
      const char *file;      /* file name            */
      const char *arg0,..., 
                 *argn;      /* arguments            */
      char *const argv[];    /* array of arguments   */
      char *const envp[];    /* environment strings  */
      

      These functions create and execute a new child process, named by path or file (depending on the form of the function used). The value of mode determines how the program is loaded, and how the parent program will behave after the child program is initiated.

      P_WAIT
      The child program is loaded into memory and executed, and then the parent program resumes execution. 
      P_NOWAIT
      Causes the parent program to execute concurrently with the new child process. 
      P_NOWAITO 
      Causes the parent program to execute concurrently with the new child process. The wait() function cannot be used to obtain the exit code.
      P_OVERLAY
      The child program replaces the parent program in memory and is executed. No return is made to the parent program.

      The various forms of the spawn functions are:

    • The l form : These contain an argument list, terminated by a NULL pointer. The argument arg0 should point to a filename that is associated with the child program.
    • The v form : These contain a pointer to an argument vector. The value in argv[0] should point to a filename that is associated with the child program. The last member of argv must be a NULL pointer. The value of argv cannot be NULL, but argv[0] can be a NULL pointer if no argument strings are passed. 
    • The p form : These use paths listed in the PATH environment variable to locate the program to be loaded, provided certain conditions are met.
    • The e form : These pass a pointer to a new environment for the child program. The argument envp is an array of character pointers to null-terminated strings. The array of pointers is terminated by a NULL pointer. The value of envp cannot be NULL, but envp[0] can be a NULL pointer, if no environment strings are passed.
      #include <stdio.h> 
      #include <process.h> 
      
      int main(void)
      {
        
        puts("Spawning child with spawnl");
        
        spawnl( P_WAIT, "child.exe",
          "child.exe", "Using spawnl", "Arg1", "Arg2", NULL );
          
        return 0;
      }
      
      /*
       * Program output:
       Spawning child with spawnl
       I am the child
       Arg 1 Using
       Arg 2 spawnl
       Arg 3 Arg1
       Arg 4 Arg2
       *
       */
      
      
      #include <stdio.h> 
      #include <process.h> 
      
      int main(void)
      {
        char *my_args[4];
        
        my_args[0] = "child.exe";
        my_args[1] = "arg1";
        my_args[2] = "arg2";
        my_args[3] = NULL;
        
        puts("Spawning child with spawnv");
        
        spawnv( P_WAIT, "child.exe", my_args);
          
        return 0;
      }
      
      /*
       * Program output:
       Spawning child with spawnv
       I am the child
       Arg 1 arg1
       Arg 2 arg2
       *
       */
       
      

      OPTION 3 - fork/exec

      Using a combination of fork and exec, you can duplicate your running program in memory, then turn the second copy into another program altogether.

      Prototypes:
      #include <sys/types.h>
      #include <unistd.h>
      pid_t fork( void );

      The exec family consists of:

      #include <unistd.h>
      int execl(   path, arg0, arg1..., argn, NULL );
      int execle(  path, arg0, arg1..., argn, NULL,
                   envp );
      int execlp(  file, arg0, arg1..., argn, NULL );
      int execlpe( file, arg0, arg1..., argn, NULL,
                   envp );
      int execv(   path, argv );
      int execve(  path, argv, envp );
      int execvp(  file, argv );
      int execvpe( file, argv, envp );
      
      const char *path;     /* file name incl. path */
      const char *file;     /* file name            */
      const char *arg0,..., 
                 *argn;     /* arguments            */
      char *const argv[];   /* array of arguments   */
      char *const envp[];   /* environment strings  */
      

      These have the same forms to the spawn functions (l, v, p and e).
      #include <stdio.h> 
      #include <stdlib.h> 
      #include <sys/types.h>
      #include <unistd.h> 
      
      
      int main(void)
      {
        char *my_args[5];
        pid_t pid;
        
        my_args[0] = "child.exe";
        my_args[1] = "arg1";
        my_args[2] = "arg2";
        my_args[3] = NULL;
        
        puts ("fork()ing");
        
        switch ((pid = fork()))
        {
          case -1:
            /* Fork() has failed */
            perror ("fork");
            break;
          case 0:
            /* This is processed by the child */
            execv ("child.exe", my_args);
            puts("Uh oh! If this prints, execv() must have failed");
            exit(EXIT_FAILURE);
            break;
          default:
            /* This is processed by the parent */
            puts ("This is a message from the parent");
            break;
        }
        
        puts ("End of parent program");
        return 0;
      }
      
      /*
       * Program output:
       fork()ing
       This is a message from the parent
       End of parent program
       I am the child
       Arg 1 arg1
       Arg 2 arg2
       *
       */
      
      

      Further options

      Windows options: (Credit: Sunlight) Use one of the _spawn functions, or CreateProcess, or ShellExecute. Which one you use depends on what you want to do. _spawn is simplest (and most portable), CreateProcess gives you the most control, ShellExecute gives you the most flexibility (starts documents as well as files, for example).

      Here are some examples of Windows versions, compliments of Fordy.

      Using CreateProcess()

      #include <windows.h> 
      
      int main(void)
      {
        char szPath[] = "C:\\WINDOWS\\system32\\Calc.exe";
        PROCESS_INFORMATION pif;  //Gives info on the thread and..
                                 //..process for the new process
        STARTUPINFO si;          //Defines how to start the program
      
        ZeroMemory(&si,sizeof(si)); //Zero the STARTUPINFO struct
        si.cb = sizeof(si);         //Must set size of structure
      
        BOOL bRet = CreateProcess(
              szPath, //Path to executable file
              NULL,   //Command string - not needed here
              NULL,   //Process handle not inherited
              NULL,   //Thread handle not inherited
              FALSE,  //No inheritance of handles
              0,      //No special flags
              NULL,   //Same environment block as this prog
              NULL,   //Current directory - no separate path
              &si,    //Pointer to STARTUPINFO
              &pif);   //Pointer to PROCESS_INFORMATION
      
        if(bRet == FALSE)
        {
          MessageBox(HWND_DESKTOP,"Unable to start program","",MB_OK);
          return 1;
        }
      
        CloseHandle(pif.hProcess);   //Close handle to process
        CloseHandle(pif.hThread);    //Close handle to thread
      
        return 0;
      }
      
      

      Using ShellExecute()
      #include <windows.h>  //You need shell32.lib for this one 
      
      int main(void)
      {
        char szPath[] = "C:\\WINDOWS\\system32\\Calc.exe";
      
        HINSTANCE hRet = ShellExecute(
              HWND_DESKTOP, //Parent window
              "open",       //Operation to perform
              szPath,       //Path to program
              NULL,         //Parameters
              NULL,         //Default directory
              SW_SHOW);     //How to open
      
        /*
        The function returns a HINSTANCE (not really useful in this case)
        So therefore, to test its result, we cast it to a LONG.
        Any value over 32 represents success!
        */
      
        if((LONG)hRet <= 32)
        {
          MessageBox(HWND_DESKTOP,"Unable to start program","",MB_OK);
          return 1;
        }
      
        return 0;
      }
      

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值