Opening new program from within a program

I want to open a new terminal window using a program just the way a window is created using the windows command prompt. I tried 'spwanl' but the child process doesnt open in a new window. Is there any other way to do that other than system(), CreateProcess and ShellExecute ?

No. You want to make OS run another program. It is impossible without using some sort of OS API.
There might be some other functions which can do what you want, but they will still be part of, in your case, WinAPI
I assume you are talking about Windows as you are talking about spawnl?

So, do you mean a way that uses a CRT function, like spawnl, exec, ... (or rather _spawnl, _exec to give then their current name [1]), rather than a Win32 call?

(Out of curiousity, what have you against CreateProcess? After all, it would normally be the neatest solution.)

None of the spawnl, exec, ... family of functions have a flag equivalent to CreateProcess's CREATE_NEW_CONSOLE.

But, if you just cannot use CreateProcess, then there is this hack. Note that the code is (probably) VC++ specific as it stands; you might need to tweak it if you use MinGW g++, etc.

Andy

[1] The names of spawnl, exec, ... were altered to _spawnl, _exec, ... in VC++ 2005 to indicate they are POSIX non-conformant. The old names are still exposed by a macro, but you should be warned that the non-_ name is deprecated. (The POSIX spawn functions all start with posix_ -- posix_spawn, ...)

Launcher program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include<iostream>
#include<cstdio>  // Edit g++ need these two includes while VC++ (2008)
#include<cstdlib> // lets you forget to include them explictly :-(
#include<process.h>

// Persuade _spawnl to run a command line app in a
// new a new console window.
//
// It does this by running cmd.exe like this:
//
// cmd.exe /s start cmd.exe /c your_program.exe arg1 arg2 ...
//
// - the first cmd.exe is told to run the start command
//   with the arguments
//
//   cmd.exe /c your_program.exe arg1 arg2 ...
//
// - the second cmd.exe runs the target with
//
//   your_program.exe arg1 arg2 ...
//
// Notes:
// - for info about cmd.exe, use "cmd /?" at the command line,
//   or google it
// - should use full paths in real code, for safety.
// - the third "comspec" in the call to _spawnl is
//   down to the way the function handles args; cmd.exe
//   is invoked just the twice
// - the use of getenv() to find out where to find cmd.exe
//   is not safe; but you shouldn't assume it's in C:\WINDOWS\system32
//   either (unless the app is for solely your use)
int main()
{
    std::cout << "Start hello.exe...\n";

    const char exepath[] = "C:\\Test\\hello.exe";

    // get COMSPEC, usually (but not always)
    // C:\Windows\System32\cmd.exe"
    char* comspec = getenv("COMSPEC");

    _spawnl( _P_NOWAIT // flags
           , comspec   // cmd line
           , comspec   // arg[0] to main (of target)
           , "/c"      // arg[1]
           , "start"   // etc (see note above)
           , comspec
           , "/c"
           , exepath
           , "one"
           , "two"
           , "three"
           , NULL    );

    std::cout << "<return> to continue...";
    std::cin.get();

    return 0;
}


Test program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// hello with arg handling

#include <stdio.h>

int main(int argc, char* argv[])
{
    printf("Hello world!\n\n");
    printf("argc = %d\n", argc);
    for(int i = 1; i < argc; ++i)
        printf("argv[%d] = %s\n", i, argv[i]);
    printf("\n");
    printf("<return> to continue...");
    getchar();

    return 0;
}
Last edited on
I'll check it out. I have another question too. When i used P_WAIT the parent process continues after the execution of child process. But when i used P_NOWAIT the child process is created ( as you can see it in the taskmanager) but it didnt execute (or rather didnt output anything on console). Only the parent process executed. Why is it so?

Also, I think arguments that are passed to the cmd.exe so that command prompt thinks that it is given the command "start <exename>". Isnt it?
Thanks for the code, it works!, although i had to make some changes in it.
Like i had to get rid of the char* comspec = getenv("COMSPEC"); and the "/c" on line 46 creates an error "Invalid switch - /c" so i had get rid of that too.
Last edited on
But when i used P_NOWAIT ... [it] didnt output anything on console

I don't have enough information to help you with that. Try adding some debug o/p to your app so you can see what it's doing behind the scenes. (You do know about OutputDebugString() and DebugView.exe, yes? If not, see end of this post.)

... arguments that are passed to the cmd.exe ... [e.g.] "start <exename>". Isnt it?

cmd.exe need to be called with /c start, not just start

cmd.exe /c start <whatever you want to be started>

/c tells cmd.exe to treat the next thing as a command

if you have a little app available (I'll use hello.exe to illustrate), try the following at the command line: cmd hello.exe

C:\Test>cmd hello.exe


the response I get is

C:\Test>cmd hello.exe
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Test>


looks the same, as if nothing has happened. But I'm now using a new instance of cmd.exe inside the original one, as can be seen from Task Manager's process list.

This time, after exiting the space instance (with exit), I type cmd /c hello.exe

C:\Test>cmd hello.exe
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Test>exit

C:\Test>cmd /c hello.exe
Hello world!

argc = 1

<return> to continue...


This time my app ran! And when my app closes, and the command it's been asked to run has finished, the spare instance of cd.exe exits autoatically.

So I think you might look at the parameters more closely, as it's possible something's not quite right in your code. The removal of the /c is a bit worrying, as I hope you can see from the above brief demo.

(If you can't repair your code, include a paste of you call to spawnl() plus the details of all the parameters you're using.)

Andy

OutputDebugString function
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363362%28v=vs.85%29.aspx

DebugView v4.81
http://technet.microsoft.com/en-gb/sysinternals/bb896647.aspx
Last edited on
Yes i do know that "/c" makes the cmd.exe interpret the string that follows as a command as you would manually type in the console. I just wanted to confirm whether i am right or wrong regarding the "/c". Not removing the "/c" in the line 46 of the code that you posted creates an error in the cmd.exe - "invalid switch - /c". You said that i might need to change the code a little bit since it was optimized for VC++. But i use MinGW compiler Code::Blocks.
Last edited on
You said that i might need to change the code a little bit

Yes, but I was thinking about _spawnl vs spawnl (the name), nothing else should have been a problem for MinGW's version of g++.

Just tries with g++, now I know that's what you use. There were two missing headers.

1
2
#include<cstdio>
#include<cstdlib> 


The VC++ header do have a habit of including stuff for you behind the scene, which I managed to miss while sorting out cmd.exe's behaviour. :-(

Also patched code above (inc. adding _P_NOWAIT)

Andy

PS While I did forget the headers, the functions are pretty standard ones...

genenv <cstdlib>
http://www.cplusplus.com/reference/cstdlib/getenv/?kw=getenv
sprintf <cstdio>
http://www.cplusplus.com/reference/cstdio/sprintf/?kw=sprintf
Last edited on
Although the code is cool enough, the point is that the cmd.exe itself must be using some or the other WinAPI, as you had said earlier.
cmd.exe itself must be using some or the other WinAPI

Yep. What did you expect?

Going back to your opening post:

I want to open a new terminal window using a program just the way a window is created using the windows command prompt. I tried 'spwanl' but the child process doesnt open in a new window. Is there any other way to do that other than system(), CreateProcess and ShellExecute ?

As MiiNiPaa has already stated, you have to use a Win32 call either directly or indirectly; everything the C runtime does relating to system functionality on Windows, it does using the Win32 API.
http://www.cplusplus.com/forum/beginner/103383/#msg556704

As you mentioned the C runtime's _spawnl function -- which itself uses CreateProcess -- I thought you just wanted to avoid a direct call.

Now I don't think I understand what you want to do!?

Andy
Last edited on
Yes i understand that for creating a process, you need to use some OS specific soln. But just as we passed the arguments to the _spawnl for cmd.exe i tried passing some arguments like "mount", etc to _spwanl for executing the DOSBox.exe. Although the DOSBox executed but it just ignores the arguments passed. Is there any way to do so ? I would like any soln like CreateProcess or ShellExecute.
Last edited on
Topic archived. No new replies allowed.