代码之家  ›  专栏  ›  技术社区  ›  Happy Day

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

  •  2
  • Happy Day  · 技术社区  · 11 年前

    我一直在为我的控制台应用程序、记录器创建新的控制台窗口。该代码适用于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 );
    }
    

    该代码在应用程序为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失败<2>时;,当我被设置时,TCHAR程序[]=TEXT(“application.exe”);-他们启动该程序的许多副本,当我被设置为NULL时,他们会返回我<87>错误他们将日志发送到主控制台窗口(应用程序窗口)。

    1 回复  |  直到 11 年前
        1
  •  3
  •   Community CDub    4 年前

    你不能。根据 AllocConsole :

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

    更多信息

    你不能使用 CREATE_NEW_PROCESS DETACHED_PROCESS 在一起看见 Process Creation Flags 我想你误解了什么 分离处理 是。从文件来看:

    分离处理

    对于控制台进程,新进程不会继承其父进程的控制台(默认)。新进程可以在以后调用AllocConsole函数来创建控制台。有关详细信息,请参见控制台的创建。

    此值不能与CREATE_NEW_CONSOLE一起使用。

    分离的进程是一个没有控制台的进程。不能为没有控制台的进程创建新控制台。

    从您的呼叫中删除DETACHED_PROCESS标志,它应该会起作用。