Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CreateProcess( ) doesn't create a new window with CREATE_NEW_CONSOLE flag - C/C++

I've been trying to create a process with CreateProcess() using the Windows API of course. I haven't been able to create a new console for some reason even after scouring the web.

Reasearch I've Done :

I used the MSDN example code as a base for the parameters I should use in the function :

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

I read the following MSDN article for information on how you should create new console windows :

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

I also read a similar SO problem to mine about someone having the same problem :

CreateProcess does not create additional console windows under Windows 7?

Results :

I've written the code I will post below with all the requirements needed to create a new console, but it doesn't behave as expected. I've spent a long time trying to find the answer on my own, but the articles above were the only relevant ones I could find through google. What happens is that the process is created, but it is inside my C program's console. I want to be able to create the process without it inherting my program's console.

There are also other discrepancies as well. If I print lots of characters in my do-while loop without a Sleep() to slow it down, TerminateProcess() will fail with Access Denied and the program will crash when I press the escape key. This is also not desired behavior.

Here is the C program that I have right now :

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define WIN32_LEAN_AND_MEAN
#include <process.h>
#include <windows.h>

#define IS_PRESSED( vk ) ( GetAsyncKeyState( vk ) & 0x8000 )

typedef struct process
{
    PROCESS_INFORMATION p_info;
    STARTUPINFO s_info;
} process;

void win_error( char * message, int is_exit )
{

    char buffer[BUFSIZ] = { 0 };
    DWORD error_code = GetLastError( );

    FormatMessage
    (
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        error_code,
        MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
        ( LPTSTR ) buffer,
        BUFSIZ,
        NULL
    );

    MessageBox( NULL, buffer, message, MB_ICONWARNING | MB_OK );

    if ( is_exit ) exit( error_code );

    return;
}

int create_process( process * p, const char * exe_path, const char * cmd_line_args )
{
    p->s_info.cb = sizeof( STARTUPINFO );
    p->s_info.dwFlags |= CREATE_NEW_CONSOLE;

    return CreateProcess(
                            exe_path,
                            ( LPSTR )cmd_line_args,
                            NULL,
                            NULL,
                            FALSE,
                            0,
                            NULL,
                            NULL,
                            &p->s_info,
                            &p->p_info
                        );
}

int main( )
{
    process p = { { 0 }, { 0 } };

    srand( time( NULL ) );

    if ( !create_process( &p, "J:\\C programs and compiliers\\C\\WindowsTest\\bin\\Debug\\matrix.bat", NULL ) )
        win_error( "CreateProcess", 1 );

    CloseHandle( p.p_info.hThread );

    do
    {
        if ( IS_PRESSED( VK_ESCAPE ) )
            if ( !TerminateProcess( p.p_info.hProcess, 0 ) )
                win_error( "TerminateProcess", 0 );

        Sleep( 50 );

    } while ( WaitForSingleObject( p.p_info.hProcess, 0 ) != WAIT_OBJECT_0 );

    CloseHandle( p.p_info.hProcess );

    return 0;
}

Here is the Batch program I'm calling :

@echo off
setlocal enabledelayedexpansion

:start
echo Hello PSAPI on Windows...
pause >nul
exit

I'm expecting someone will know how to mess with processes more than I do. This is my first time using the CreateProcess() function. Yes, I am aware of ShellExecute(). I am also aware that my Batch file isn't a matrix, but I wanted to start simple.

like image 975
TheDelightfulEnd Avatar asked Dec 19 '13 21:12

TheDelightfulEnd


1 Answers

CREATE_NEW_CONSOLE is a flag of CreateProcess() itself, not of STARTUPINFO. You are putting the flag in the wrong place. Try this instead:

int create_process( process * p, const char * exe_path, const char * cmd_line_args )
{
    ...
    return CreateProcessA(
                            exe_path,
                            cmd_line_args,
                            NULL,
                            NULL,
                            FALSE,
                            CREATE_NEW_CONSOLE, // <-- here
                            NULL,
                            NULL,
                            &p->s_info,
                            &p->p_info
                        );
}

Also, keep in mind that a STARTUPINFOEX can be passed to CreateProcess(), so your create_process() function should not be forcing p->s_info.cb, that should be the caller's responsibility depending on whether a STARTUPINFO or a STARTUPINFOEX is being used.

like image 99
Remy Lebeau Avatar answered Sep 22 '22 16:09

Remy Lebeau