Home > Software engineering >  How to distinguish if console program is opened in Powershell or in Windows Terminal?
How to distinguish if console program is opened in Powershell or in Windows Terminal?

Time:06-11

I'm programming a library which will make setting colors, modes, etc. easier in console program. But I've encountered a problem with Windows Terminal. For example I have a function:

void WindowsCLI::setUnderlinedFont()
{
    auto consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    config.underlined = true;
    SetConsoleTextAttribute(consoleHandle, getTextAttribute(config));
}

and it uses COMMON_LVB_UNDERSCORE attribute from windows.h to make text underlined. And the result of this function in powershell looks like this: enter image description here, and in Windows Terminal like this:enter image description here, so apparently in the second case my function didn't work properly. I thought that the problem is that the Windows Terminal runs in virtual terminal mode. So I made another function for virtual terminals:

void WindowsVirtualCLI::setUnderlinedFont()
{
    printf("\x1b[4m");
}

and now it didn't work for Powershell: enter image description here, and worked properly for Windows Terminal: enter image description here. But now I have another problem. How to distinguish that the program is run in Powershell or Windows Terminal. I tried using this function:

CLI& cli()
{
    DWORD consoleMode;
    auto consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
    GetConsoleMode(consoleHandle, &consoleMode);

    if ((consoleMode & ENABLE_PROCESSED_OUTPUT) && (consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
    {
        return windows::WindowsVirtualCLI::getInstance();
    }
    else
    {
        return windows::WindowsCLI::getInstance();
    }
}

But it turned out that both Powershell and Windows Terminal have ENABLE_PROCESSED_OUTPUT and ENABLE_VIRTUAL_TERMINAL_PROCESSING enabled. And now, I have no other idea how can I distinguish these terminals in runtime. Do you have any idea how?

P.S. I have changed cli() method to this:

CLI& cli()
{
    DWORD consoleMode;
    auto consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    GetConsoleMode(consoleHandle, &consoleMode);
    SetConsoleMode(consoleHandle, consoleMode);

    if ((consoleMode & ENABLE_PROCESSED_OUTPUT) && (consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
    {
        return windows::WindowsVirtualCLI::getInstance();
    }
    else
    {
        return windows::WindowsCLI::getInstance();
    }
}

And still it doesn't work as I need to.

CodePudding user response:

A simple way to detect whether you're running in Windows Terminal is to check if the WT_SESSION environment variable is defined (has a value).

According to this answer, getenv("WT_SESSION") should work for retrieving the value of that variable, if defined.

Note:

  • This isn't foolproof, because if you launch a regular console window (conhost.exe) from a shell running in Windows Terminal, it'll likely inherit the WT_SESSION variable.

  • The more cumbersome alternative is to walk the (chain of) parent processes to look for a process named WindowsTerminal.

  • Related