2

I am stuck on create new console window for my console application, for logger. That code works fine for GUI apps, but not work for console, and they require: CreateProcess function with the DETACHED_PROCESS flag.

Logger Log;    
DWORD PiD;

void __stdcall LoggerCore(PVOID pVoid)
{             
    AllocConsole();
    while(true)
    {
        SetConsoleTitleA(Log.LoggerTittle()); 
        Sleep(5000);
    }
    _endthread();
}            

char* Logger::LoggerTittle()
{
    static char Tittle[55]; 
    sprintf(Tittle, "Debug Logger");  
    return Tittle;
} 

void Logger::LoggerInit()
{   
  CreateThread( 0 , 0 , (LPTHREAD_START_ROUTINE) LoggerCore , 0 , 0 , &PiD );
}

And that code, create a new console when app is GUI, and display "Log.ConsoleOutPut(1, c_Green,t_Default,"Debug Logger: SomeInfo");" in new console window. But all of that, not work for console application. So, how i can make a second console window in console application by using CreateProcess? Thanks for advice!

So, i am try to re-write it, but nothing... that is not works for me.

#include logger.h
char Message[1024];

Logger Log;    

DWORD PiD;
/*

void __stdcall LoggerCore(PVOID pVoid)
{             
    AllocConsole();
    while(true)
    {
        SetConsoleTitleA(Log.LoggerTittle()); 
        Sleep(5000);
    }
    _endthread();
}            

char* Logger::LoggerTittle()
{
    static char Tittle[55]; 
    sprintf(Tittle, "Debug Logger");  
    return Tittle;
} 
*/
void Logger::LoggerInit()
{   
    SECURITY_ATTRIBUTES sa;
    sa.nLength=sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle=1;
    sa.lpSecurityDescriptor=0;
    SetHandleInformation(this->near_end,HANDLE_FLAG_INHERIT,0);
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&pi,sizeof(pi));
    ZeroMemory(&si,sizeof(si));
    si.cb=sizeof(STARTUPINFO);
    si.dwFlags|=STARTF_USESTDHANDLES;
    TCHAR program[]=TEXT("???");//need type something here.
    TCHAR arguments[100];

    if (!CreateProcess(program,arguments,0,0,1,CREATE_NEW_CONSOLE,0,0,&si,&pi))
     printf( "CreateProcess failed (%d).\n", GetLastError() );
     return;

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    this->process=pi.hProcess;
    CloseHandle(pi.hThread);

 // CreateThread( 0 , 0 , (LPTHREAD_START_ROUTINE) LoggerCore , 0 , 0 , &PiD );
}


void Logger::CheckProcent(char* message)
{
    for (UINT i = 0; i <= strlen(message); i++)
    {                                                  
        if(message[i] == '%')         
        {
            for(UINT j = strlen(message); j >= i; j--)        
                message[j+1] = message[j];
            i++;
        }
    }
}

void Logger::ConsoleOutPut(int WOL, sColor Color, sLogType Type, const char* Format, ...)
{                   
    SYSTEMTIME t;
    GetLocalTime(&t);
    DWORD dwBytesWritten;
    HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE hStdin;
    hStdin = GetStdHandle(STD_INPUT_HANDLE);

    if (hStdin == INVALID_HANDLE_VALUE)
        ExitProcess(1);

    va_list pArguments;
    va_start(pArguments, Format);
    sprintf(Message,Format, pArguments);
    CheckProcent(Message); // "%" Bug Fix 
    va_end(pArguments);

    char currdate[11] = {0};
    char outputmsg[2048];
    if(WOL == 1)
    {
        sprintf(currdate, "(%02d:%02d:%02d)", t.wHour, t.wMinute, t.wSecond);
        sprintf(outputmsg,"%s %s\n", currdate,Message);
    }
    else
        sprintf(outputmsg,"%s\n", Message); 

    switch(Color)
    {
    case c_BoldGreen: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_INTENSITY);
        break;
    case c_BoldRed: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_RED );
        break;
    case c_Red: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_RED | FOREGROUND_INTENSITY);
        break;
    case c_Green: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        break;
    case c_Blue: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_BLUE | FOREGROUND_INTENSITY);
        break;
    case c_Cyan: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
        break;
    case c_Yellow: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        break;
    case c_Magenta: 
        SetConsoleTextAttribute(this->Handle(FALSE),FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
        break;
    case c_Grey:
        SetConsoleTextAttribute(this->Handle(FALSE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
        break;
    } 

    CreateLog(Type,outputmsg); 
    WriteFile(this->Handle(FALSE), outputmsg, strlen(outputmsg), &dwBytesWritten, NULL);
    SetConsoleTextAttribute(this->Handle(FALSE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    return;
}

HANDLE Logger::Handle(BOOL Input)
{
    if(Input==TRUE)
        return GetStdHandle(STD_INPUT_HANDLE);
    else
        return GetStdHandle(STD_OUTPUT_HANDLE);
}

void Logger::CreateLog(sLogType Type,const char* Format, ...)
{
    SYSTEMTIME now;
    GetLocalTime(&now);  

    char ConsoleLog[55];
    char CommandsLog[55]; 
    char ErrorLog[55];
    char Date[55];
    char SqlLog[55];
    char TestLog[55];
    sprintf(Date, ".\\Logger\\%02d-%02d-%02d\\", now.wDay, now.wMonth, now.wYear); 
    CreateDirectory(Date,NULL);

    sprintf(CommandsLog, ".\\Logger\\%02d-%02d-%02d\\Commands.log", now.wDay, now.wMonth, now.wYear); 
    sprintf(ConsoleLog, ".\\Logger\\%02d-%02d-%02d\\CONSOLE.log", now.wDay, now.wMonth, now.wYear);     
    sprintf(ErrorLog, ".\\Logger\\%02d-%02d-%02d\\Error.log", now.wDay, now.wMonth, now.wYear);
    sprintf(SqlLog, ".\\Logger\\%02d-%02d-%02d\\Sql.log", now.wDay, now.wMonth, now.wYear);
    sprintf(TestLog, ".\\Logger\\%02d-%02d-%02d\\Test.log", now.wDay, now.wMonth, now.wYear);

    va_list pArguments1;
    va_start(pArguments1, Format);
    sprintf(Message,Format, pArguments1);
    va_end(pArguments1);

    switch (Type)
    {
        case t_NULL:
        break;

        case t_Error:
        {
            SaveFile(ErrorLog, Message);
        }
        break;
        case t_Default: 
        {
            SaveFile(ConsoleLog,Message);
        }
        break;  
        case t_COMMANDS:
        {                                   
            SaveFile(ConsoleLog,Message);
            SaveFile(CommandsLog,Message);
        }
        break;
        case t_SQL: 
        {                                      
            SaveFile(ConsoleLog,Message);
            SaveFile(SqlLog,Message);
        }
        break;
        case t_TEST:
        {
            SaveFile(TestLog,Message);
        }
        break;
    }
}

void Logger::SaveFile(char *logString,char *Message)
{
    FILE *stream;  
    stream=fopen(logString, "a+" );
    fprintf(stream, "%s", Message);
    fclose(stream);
}

So, now my problem is - CreateProcess failed <2>, and when i am set TCHAR program[]=TEXT("application.exe"); - they launch many copies of that program, when i am set param in NULL - they return me <87> error... And they send logs to primary console window (app window).

Happy Day
  • 297
  • 1
  • 5
  • 14
  • A process can own only one console window. That it works for a GUI app is just an illusion, it still has only one console window. – Hans Passant Sep 13 '13 at 14:34
  • When `CreateProcess` fails, call `GetLastError()` to get error information. That will help you determine why it's failing. – Jim Mischel Sep 13 '13 at 14:48
  • I don't see the code that calls `LoggerInit`. You only want to call that one time in your application. If you want to send log information from one application to another, you need to set up some kind of interprocess communication like a named pipe. – Jim Mischel Sep 13 '13 at 21:55
  • Ahh, that it is. So, my console application - is simple server software. And that logger - part of it, and that calls when that server application startup : Log.LoggerInit();//init the Logger And send to console message Log.ConsoleOutPut(0, c_Green,t_NULL,"Logger Active"); I am understand now 90% how it work (CreateProcess), but i cant understand, what need write to program[]=TEXT... for prevent open lots of console windows, and if i am put here something like cmd.exe or other app - they give me error. If appName = serverApp, they open a many consoles (becouse logger code - part of that app) – Happy Day Sep 13 '13 at 22:43
  • I am found a some example, but here the question. Please look this http://www.cplusplus.com/forum/lounge/17371/ Question is: that should be "Server" side from that example in my server-app, and "Client" as compiled console application? Or here exist the way to make it both in one (my server-app) application? (And program name in server side, should be that compiled "Client" console app?) – Happy Day Sep 13 '13 at 22:55

1 Answers1

3

You can't. According to the documentation for AllocConsole:

A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console.

More info

You can't use CREATE_NEW_PROCESS and DETACHED_PROCESS together. See Process Creation Flags. I think you misunderstand what DETACHED_PROCESS is. From the documentation:

DETACHED_PROCESS

For console processes, the new process does not inherit its parent's console (the default). The new process can call the AllocConsole function at a later time to create a console. For more information, see Creation of a Console.

This value cannot be used with CREATE_NEW_CONSOLE.

A detached process is a process without a console. You can't create a new console for a process that doesn't have a console.

Remove the DETACHED_PROCESS flag from your call, and it should work.

Community
  • 1
  • 1
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • yeah, i am know, but idk, how to use CreateProcess correctly, i am post of example, but here - nothing happen, and logger contain spam messages inside my console application =( – Happy Day Sep 13 '13 at 14:41
  • So, re-make them, but it show me CreateProcess Failed 87, i am think, problem in code & TCHAR program[]=TEXT("logger.exe"), when i am put here name of console app executable, they start open it again and again in cycle. – Happy Day Sep 13 '13 at 15:09