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

Create new console from console app? C++

本文关键字:控制台 C++ 创建 应用      更新时间:2023-10-16

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

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,"调试记录器: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 %sn", currdate,Message);
    }
    else
        sprintf(outputmsg,"%sn", 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);
}

所以,现在我的问题是 - 创建过程失败<2>,当我设置 TCHAR 程序[]=TEXT("应用程序.exe"); - 当我在 NULL 中设置参数时,他们启动该程序的许多副本 - 他们返回我 <87> 错误...他们将日志发送到主控制台窗口(应用程序窗口)。

你不能。根据 AllocConsole 的文档:

一个进程

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

更多信息

您不能同时使用CREATE_NEW_PROCESSDETACHED_PROCESS。请参阅进程创建标志。我想你误解了DETACHED_PROCESS是什么。从文档中:

DETACHED_PROCESS

对于控制台进程

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

此值不能与CREATE_NEW_CONSOLE一起使用。

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

从呼叫中删除DETACHED_PROCESS标志,它应该可以工作。