从控制台应用创建新控制台? C ++

时间:2013-09-13 13:08:24

标签: c++ multithreading console-application

我坚持为我的控制台应用程序创建新的控制台窗口,用于记录器。该代码适用于GUI应用程序,但不适用于控制台,它们需要:带有DETACHED_PROCESS标志的CreateProcess函数。

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 );
}

该代码,当app为GUI时创建一个新控制台,并显示“Log.ConsoleOutPut(1,c_Green,t_Default,”Debug Logger:SomeInfo“);”在新的控制台窗口中。但所有这些,不适用于控制台应用程序。那么,我如何使用CreateProcess在控制台应用程序中创建第二个控制台窗口?谢谢你的建议!

所以,我试着重写它,但没有......这对我不起作用。

#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);
}

所以,现在我的问题是 - CreateProcess失败&lt; 2&gt;,当我设置TCHAR program [] = TEXT(“application.exe”); - 当我设置为NULL时,他们会启动该程序的许多副本 - 他们返回我&lt; 87&gt;错误......他们将日志发送到主控制台窗口(应用程序窗口)。

1 个答案:

答案 0 :(得分:2)

你做不到。根据{{​​3}}的文档:

  

进程只能与一个控制台关联,因此如果调用进程已有控制台,则AllocConsole函数将失败。

更多信息

您不能同时使用CREATE_NEW_PROCESSDETACHED_PROCESS。见AllocConsole。我想你误解了DETACHED_PROCESS是什么。来自文档:

  

<强> DETACHED_PROCESS

     

对于控制台进程,新进程不会继承其父进程控制台(默认值)。新进程可以稍后调用AllocConsole函数来创建控制台。有关更多信息,请参阅创建控制台。

     

此值不能与CREATE_NEW_CONSOLE一起使用。

分离进程是没有控制台的进程。您无法为没有控制台的进程创建新控制台。

从您的通话中删除DETACHED_PROCESS标志,它应该可以正常工作。