Conheça o Pseudo Console do Windows (ConPTY)

Artigo publicado em 2 de agosto de 2018

Este é o segundo artigo sobre a linha de comando do Windows, onde discutiremos a nova infraestrutura e interfaces de programação do pseudo console do Windows, ou seja, o Windows Pseudo Console (ConPTY): por que o desenvolvemos, por que é necessário, como funciona, como usá-lo e muito mais.

No último artigo, “O grave legado do passado. Problemas na linha de comando do Windows ” falamos sobre os pré-requisitos para o surgimento do terminal e a evolução da linha de comando no Windows, e também começamos a estudar a estrutura interna do console do Windows e a infraestrutura da linha de comando do Windows. Também discutimos as muitas vantagens e principais desvantagens do console do Windows.

Uma das desvantagens é que o Windows está tentando ser "útil", mas interfere nos desenvolvedores de consoles alternativos e de terceiros, desenvolvedores de serviços etc. Ao criar um console ou serviço, os desenvolvedores precisam ter acesso aos canais de comunicação através dos quais seus terminais / serviços trocam dados com aplicativos de linha de comando ou fornecem acesso a eles. No mundo * NIX, isso não é um problema, pois o * NIX fornece uma infraestrutura de pseudo-terminal (PTY) que facilita a criação de canais de comunicação para um console ou serviço. Mas no Windows não era ...

... até agora!

De TTY para PTY


Antes de falar em detalhes sobre o nosso desenvolvimento, voltemos brevemente ao desenvolvimento de terminais.

No começo era TTY


Como discutido em um artigo anterior , nos primeiros dias da computação, os usuários controlavam computadores usando teletipos eletromecânicos (TTYs) conectados a um computador através de algum tipo de canal de comunicação serial (geralmente através de um loop de corrente de 20 mA ).


Ken Thompson e Dennis Ritchie (em pé) trabalham no teletipo DEC PDP-11 (mensagens sem display eletrônico)

Distribuição Terminal


Os teletipos foram substituídos por terminais computadorizados com displays eletrônicos (geralmente telas CRT). Normalmente, os terminais são dispositivos muito simples (daí o termo "terminal burro"), contendo apenas os componentes eletrônicos e a capacidade de processamento necessários para as seguintes tarefas:

  1. Recepção da entrada de texto do teclado.
  2. Armazenar em buffer o texto digitado em uma linha (incluindo a edição local antes do envio).
  3. Envio / recebimento de texto em um canal serial (geralmente através da interface RS-232 outrora onipresente).
  4. Exibição do texto recebido no visor do terminal.

Apesar de sua simplicidade (ou talvez graças a isso), os terminais rapidamente se tornaram a principal ferramenta para gerenciar minicomputadores, mainframes e servidores: a maioria dos operadores de entrada de dados, operadores de computadores, administradores de sistemas, cientistas, pesquisadores, desenvolvedores de software e luminárias da indústria trabalhavam nos terminais DEC, IBM, Wyse e muitos outros.


Almirante Grace Hopper em seu escritório com um terminal DEC VT220 em sua mesa

Distribuição de terminais de software


Desde meados da década de 1980, em vez de terminais especializados, computadores de uso geral começaram a ser gradualmente utilizados, que se tornaram mais acessíveis, populares e poderosos. Muitos computadores antigos e outros computadores dos anos 80 tinham aplicativos de terminal que abriam a conexão RS-232 e trocavam dados com qualquer pessoa do outro lado da conexão.

À medida que os computadores de uso geral se tornaram mais sofisticados, uma interface gráfica com o usuário (GUI) e um mundo totalmente novo de aplicativos simultâneos, incluindo aplicativos de terminal, apareceram.

Mas havia um problema: como um aplicativo de terminal pode interagir com outro aplicativo de linha de comando em execução na mesma máquina? E como conectar fisicamente um cabo serial entre dois aplicativos em execução no mesmo computador?

Aparência do pseudo terminal (PTY)


No mundo * NIX, o problema foi resolvido com a introdução de um pseudo terminal (PTY) .

O PTY emula equipamentos de telecomunicações seriais em um computador, expondo os pseudo-dispositivos mestre e escravo ("mestre" e "escravo"): os aplicativos de terminal se conectam ao pseudo-dispositivo mestre e os aplicativos de linha de comando (por exemplo, invólucros como cmd, PowerShell e bash) se conectam ao pseudo-dispositivo escravo. Quando um cliente de terminal transmite texto e / ou comandos de controle (codificados como texto) para o pseudo-dispositivo mestre, o texto é traduzido para o escravo associado a ele. O texto do aplicativo é enviado ao pseudo-dispositivo escravo, depois de volta ao mestre e, assim, ao terminal. Os dados são sempre enviados / recebidos de forma assíncrona.


Aplicativo pseudo-terminal / Shell

É importante observar que o pseudo-dispositivo “escravo” emula o comportamento do terminal físico e converte os caracteres de comando em sinais POSIX. Por exemplo, se o usuário digitar CTRL + C no terminal, o valor ASCII para CTRL + C (0x03) será enviado pelo mestre. Quando recebido em um pseudo-dispositivo escravo, o valor 0x03 é removido do fluxo de entrada e um sinal SIGINT é gerado.

Essa infraestrutura PTY é amplamente usada por aplicativos de terminal * NIX, gerenciadores de painel de texto (por exemplo, screen, tmux) etc. Esses aplicativos chamam openpty() , que retorna um par de descritores de arquivo (fd) para o mestre e o escravo PTY. Em seguida, o aplicativo pode bifurcar / executar um aplicativo de linha de comando filho (por exemplo, bash), que usa seus escravos fd para ouvir e retornar texto ao terminal conectado.

Esse mecanismo permite que os aplicativos de terminal "conversem" diretamente com os aplicativos de linha de comando em execução localmente, assim como um terminal conversaria com um computador remoto por meio de uma conexão serial / rede.

O que, sem pseudo-console do Windows?


Como discutimos no artigo anterior, embora o console do Windows seja conceitualmente semelhante ao terminal * NIX tradicional, ele difere de várias maneiras importantes, especialmente nos níveis mais baixos, o que pode causar problemas para os desenvolvedores de aplicativos de linha de comando do Windows, terminais / consoles e servidores de terceiros. aplicações:

  1. O Windows não possui a infraestrutura PTY : quando um usuário inicia um aplicativo de linha de comando (por exemplo, Cmd, PowerShell, wsl, ipconfig etc.), o próprio Windows "conecta" uma instância de console nova ou existente ao aplicativo.
  2. O Windows interfere nos consoles e aplicativos de servidor de terceiros : o Windows (atualmente) não fornece aos terminais uma maneira de fornecer canais de comunicação através dos quais eles desejam interagir com um aplicativo de linha de comando. Os terminais de terceiros precisam criar consoles fora da tela, enviar dados inseridos pelo usuário para lá e desfazer a saída redesenhando-os no visor do console de terceiros!
  3. Somente o Windows possui a API do console : os aplicativos de linha de comando do Windows dependem da API do Win32 Consol, que reduz a portabilidade do código, pois todas as outras plataformas oferecem suporte a texto / VT, não à API.
  4. Acesso remoto não padrão : a dependência de aplicativos de linha de comando na API Consol complica significativamente os scripts de interação e acesso remoto.

O que fazer


Muitos desenvolvedores frequentemente solicitavam um mecanismo semelhante ao PTY no Windows, especialmente aqueles que trabalham com ConEmu / Cmder, Console2 / ConsoleZ, Hyper, VSCode, Visual Studio, WSL, Docker e OpenSSH.

Até Peter Bright, editor de tecnologia da Ars Technica, me pediu para implementar o mecanismo PTY alguns dias depois, quando comecei a trabalhar na equipe do console:



E recentemente novamente:



Bem, finalmente fizemos: criamos um pseudo-console para Windows :

Bem-vindo ao Windows Pseudo Console (ConPTY)


Desde a formação da equipe do console, há cerca de quatro anos, o grupo se envolveu na revisão do console do Windows e nos mecanismos internos da linha de comando. Ao mesmo tempo, consideramos regular e cuidadosamente os problemas descritos acima e muitos outros problemas e problemas relacionados. Mas a infraestrutura e o código não estavam prontos para viabilizar o lançamento do pseudo-console ... até agora!

A nova infraestrutura, API e outras alterações relacionadas ao pseudo-console do Windows (ConPTY) eliminarão / aliviarão toda uma classe de problemas ... sem interromper a compatibilidade com aplicativos de linha de comando existentes !

A nova API Win32 ConPTY (a documentação oficial será publicada em breve) está disponível nas versões internas mais recentes do Windows 10 e no SDK do Windows 10 Insider Preview correspondente. Eles aparecerão na próxima versão principal do Windows 10 (em algum lugar no outono / inverno de 2018).

Arquitetura do console / ConHost


Para entender o ConPTY, você precisa estudar a arquitetura do console do Windows, ou melhor, o ... ConHost!

É importante entender que, embora o ConHost implemente tudo o que você vê e conhece como um aplicativo do Windows Console, o ConHost também contém e implementa a maior parte da infraestrutura de linha de comando do Windows! A partir de agora, o ConHost se torna um "nó do console" real , suportando todos os aplicativos de linha de comando e / ou aplicativos de GUI que interagem com os aplicativos de linha de comando!

Como Porque O que? Vamos dar uma olhada.

Aqui está uma visão geral da arquitetura do console interno / ConHost:



Comparado à arquitetura do artigo anterior , o ConHost agora contém vários módulos adicionais para processamento VT e o novo módulo ConPTY que implementa APIs abertas:

  • API ConPTY : As novas APIs Win32 ConPTY fornecem um mecanismo semelhante ao modelo POSIX PTY, mas na refração do Windows.
  • Interatividade VT : recebe texto de entrada na codificação UTF-8, converte cada caractere de texto exibido no registro INPUT_RECORD correspondente e o salva no buffer de entrada. Ele também processa seqüências de escape, como 0x03 (CTRL + C), convertendo-as em KEY_EVENT_RECORDS , que produzem a ação de escape apropriada.
  • Renderizador de VT : gera sequências de VT necessárias para mover o cursor e renderizar texto e estilo em áreas do buffer de saída que foram alteradas em relação ao quadro anterior.

OK, mas o que isso realmente significa?

Como os aplicativos de linha de comando do Windows funcionam?


Para entender melhor o impacto da nova infraestrutura do ConPTY, vejamos como o console do Windows e os aplicativos de linha de comando funcionaram até agora.

Sempre que um usuário inicia um aplicativo de linha de comando como Cmd, PowerShell ou ssh, o Windows cria um novo processo Win32 no qual ele carrega o binário executável do aplicativo e quaisquer dependências (recursos ou bibliotecas).

Um processo recém-criado geralmente herda os descritores stdin e stdout de seu pai. Se o processo pai for um processo da GUI do Windows, os descritores stdin e stdout estarão ausentes, portanto o Windows implantará e anexará o novo aplicativo à nova instância do console. A comunicação entre aplicativos de linha de comando e seu console é transmitida através do ConDrv.

Por exemplo, ao iniciar a partir de uma instância do PowerShell sem privilégios elevados, o novo processo de aplicativo herdará os descritores pai stdin / stdout e, portanto, receberá dados de entrada e enviará a saída para o mesmo console que o pai.

Aqui precisamos fazer uma reserva, porque, em alguns casos, os aplicativos de linha de comando são lançados anexados a uma nova instância do console, especialmente por razões de segurança, mas a descrição acima geralmente é verdadeira.

Por fim, quando o aplicativo de linha de comando / shell é iniciado, o Windows o conecta à instância do console (ConHost.exe) via ConDrv:



Como o ConHost funciona?


Sempre que um aplicativo de linha de comando estiver em execução, o Windows conectará o aplicativo a uma instância nova ou existente do ConHost. O aplicativo e sua instância do console são conectados através do driver do console no modo kernel (ConDrv), que envia / recebe mensagens IOCTL contendo solicitações de chamada de API serializadas e / ou dados de texto.

Historicamente, como declarado em um artigo anterior, o trabalho do ConHost é relativamente simples hoje:

  • O usuário gera entrada do teclado / mouse / caneta / touchpad, que é convertida em KEY_EVENT_RECORD ou MOUSE_EVENT_RECORD e armazenada no buffer de entrada.
  • O buffer de entrada é esvaziado um registro por vez, executando as ações de entrada solicitadas, como exibir texto na tela, mover o cursor, copiar / colar texto, etc. Muitas dessas ações alteram o conteúdo do buffer de saída. Essas áreas alteradas são registradas pelo mecanismo de estado do ConHost.
  • Em cada quadro, o console exibe as áreas alteradas do buffer de saída.

Quando o aplicativo de linha de comando chama a API do console do Windows, as chamadas da API são serializadas em mensagens IOCTL e enviadas pelo driver ConDrv. Em seguida, ele entrega mensagens IOCTL ao console conectado, que decodifica e executa a chamada da API solicitada. Os valores retornados / de saída são serializados de volta para a mensagem IOCTL e enviados de volta para o aplicativo via ConDrv.

ConHost: Contribuindo para o passado para o futuro


A Microsoft se esforça para manter a compatibilidade com aplicativos e ferramentas existentes sempre que possível. Especialmente para a linha de comando. De fato, as versões de 32 bits do Windows 10 ainda podem executar muitos / a maioria dos aplicativos e executáveis ​​Win16 de 16 bits!

Como mencionado acima, uma das principais funções do ConHost é fornecer serviços para seus aplicativos de linha de comando, especialmente aplicativos herdados que invocam e dependem da API do console Win32. Agora, o ConHost oferece novos serviços:

  • Infraestrutura perfeita do tipo PTY para comunicação com consoles e terminais modernos
  • Atualizando aplicativos de linha de comando tradicionais / herdados
    • Recebendo e convertendo texto UTF-8 / VT em registros de entrada (como se fossem inseridos pelo usuário)
    • A API do console chama o aplicativo hospedado, atualizando seu buffer de saída de acordo
    • Exibir áreas modificadas do buffer de saída na codificação UTF-8, texto / VT

A seguir, é apresentado um exemplo de como um aplicativo de console moderno se comunica com um aplicativo de linha de comando por meio do ConPTY ConHost.



Neste novo modelo:

  1. Console:
    1. Cria canais de comunicação próprios
    2. Chama a API ConPTY para criar o ConPTY, forçando o Windows a executar uma instância do ConHost conectada à outra extremidade dos canais
    3. Cria uma instância de um aplicativo de linha de comando (por exemplo, PowerShell) conectado ao ConHost, como de costume
  2. Conhost:
    1. Lê texto UTF-8 / VT na entrada e o converte em registros INPUT_RECORD , que são enviados ao aplicativo de linha de comando
    2. Faça chamadas de API a partir de um aplicativo de linha de comando que possa modificar o conteúdo do buffer de saída
    3. Exibe alterações no buffer de saída na codificação UTF-8 (texto / VT) e envia o texto recebido para seu console
  3. Aplicativo de linha de comando:
    1. Funciona como de costume, lê a entrada e chama a API do console, sem ter idéia de que seu ConPTY ConHost converte entrada e saída de / para UTF-8!

O último momento é importante! Quando o aplicativo de linha de comando antigo usa chamadas para a API do console como WriteConsoleOutput(...) , o texto especificado é gravado no buffer de saída ConHost correspondente. Periodicamente, o ConHost exibe as áreas alteradas do buffer de saída como texto / VT, que é enviado via stdout de volta ao console.

Por fim, até os aplicativos de linha de comando tradicionais de fora "falam" o texto / TV sem nenhuma alteração !

Usando a nova infraestrutura ConPTY, os consoles de terceiros agora podem interagir diretamente com aplicativos de linha de comando modernos e tradicionais e trocar todos eles em texto / VT.

Interagindo remotamente com aplicativos de linha de comando do Windows


O mecanismo descrito acima funciona bem em um computador, mas também ajuda na interação, por exemplo, com uma instância do PowerShell em um computador Windows remoto ou em um contêiner.

Há um problema ao iniciar um aplicativo de linha de comando remotamente (ou seja, em computadores, servidores ou contêineres remotos). O fato é que os aplicativos de linha de comando em máquinas remotas se comunicam com a instância local do ConHost, porque as mensagens IOCTL não foram projetadas para serem transmitidas pela rede. Como transferir entrada do console local para a máquina remota e como obter a saída do aplicativo em execução lá? Além disso, o que fazer com máquinas Mac e Linux, onde existem terminais, mas nenhum console compatível com Windows?

Portanto, para controlar remotamente a máquina Windows, precisamos de algum tipo de intermediário de comunicação que possa serializar dados de forma transparente na rede, gerenciar o tempo de vida da instância do aplicativo etc.

Talvez algo como ssh ?

Felizmente, o OpenSSH foi recentemente portado para o Windows e adicionado como uma opção adicional ao Windows 10 . O PowerShell Core também usa ssh como um dos protocolos de comunicação remota suportados do PowerShell Core Remoting . E para aqueles que executam o Windows PowerShell, a comunicação remota com o Windows PowerShell ainda é uma opção aceitável.

Vamos ver como o OpenSSH for Windows agora permite controlar remotamente shells do Windows e aplicativos de linha de comando:



O OpenSSH atualmente inclui algumas complicações indesejadas:

  1. Usuário:
    1. Inicia o cliente ssh e o Windows conecta a instância do console como de costume
    2. Insere texto no console, que envia pressionamentos de teclas para o cliente ssh
  2. cliente ssh:
    1. Lê a entrada como bytes de dados de texto
    2. Envia dados de texto pela rede para o serviço de escuta sshd
  3. O serviço sshd passa por vários estágios:
    1. Inicia o shell padrão (por exemplo, Cmd), que força o Windows a criar e conectar uma nova instância do console
    2. Localiza e se conecta ao console da instância Cmd
    3. Move o console para fora da tela (e / ou oculta)
    4. Envia a entrada recebida do cliente ssh para o console fora da tela como entrada
  4. A instância do cmd funciona como sempre:
    1. Coleta entrada do serviço sshd
    2. Faz o trabalho
    3. Chama a API do console para renderizar / estilizar texto, mover o cursor etc.
  5. Console [fora da tela] conectado:
    1. Faça chamadas de API atualizando o buffer de saída.
  6. Serviço sshd:
    1. Recolhe o buffer de saída do console fora da tela, encontra as diferenças, as codifica em texto / VT e envia de volta ...
  7. Um cliente ssh que envia texto ...
  8. Console que exibe texto

Divertido, certo? Nem um pouco! Nessa situação, muita coisa pode dar errado, especialmente no processo de simulação e envio de entrada do usuário e liberação do buffer de saída de um console fora da tela. Isso leva à instabilidade, falhas, corrupção de dados, consumo excessivo de energia, etc. Além disso, nem todos os aplicativos fazem o trabalho de remover não apenas o texto em si, mas também suas propriedades, e é por isso que a formatação e a cor são perdidas!

Trabalho remoto usando o moderno ConHost e ConPTY


Certamente podemos melhorar a situação? Sim, é claro que podemos - vamos fazer algumas mudanças na arquitetura e aplicar nosso novo ConPTY:



O diagrama mostra que o circuito mudou da seguinte maneira:

  1. Usuário:
    1. Inicia o cliente ssh e o Windows conecta a instância do console como de costume
    2. Insere texto no console, que envia pressionamentos de teclas para o cliente ssh
  2. cliente ssh:
    1. Lê a entrada como bytes de dados de texto
    2. Envia dados de texto pela rede para o serviço de escuta sshd
  3. Serviço sshd:
    1. Cria canais stdin / stdout
    2. Chama a API ConPTY para iniciar o ConPTY
    3. Inicia uma instância do Cmd conectada à outra extremidade do ConPTY. Windows inicia e monta uma nova instância do ConHost
  4. A instância do cmd funciona como sempre:
    1. Coleta entrada do serviço sshd
    2. Faz o trabalho
    3. Chama a API do console para renderizar / estilizar texto, mover o cursor etc.
  5. Instância ConPTY ConHost:
    1. Faça chamadas de API atualizando o buffer de saída.
    2. Exibe as regiões alteradas do buffer de saída como texto / VT codificado em UTF-8, que é enviado de volta ao console / terminal via ssh

Essa abordagem usando o ConPTY é claramente mais limpa e mais simples para o serviço sshd. As chamadas para a API do console do Windows são feitas inteiramente na instância ConHost do aplicativo de linha de comando, que converte todas as alterações visíveis em texto / VT. Quem quer que se conecte ao ConHost, ele não precisa saber que o aplicativo chama a API do console e não gera texto / VT!

Concorde que esse novo mecanismo de comunicação remota ConPTY leva a uma arquitetura elegante, consistente e simples. Combinada com os poderosos recursos incorporados ao ConHost, suporte para aplicativos mais antigos e exibição de alterações nos aplicativos que chamam as APIs do console do console como texto / VT, a nova infraestrutura do ConHost e do ConPTY nos ajuda a mudar o passado para o futuro.

API ConPTY e como usá-la


A API ConPTY está disponível na versão atual do SDK do Windows 10 Insider Preview .

Até agora, tenho certeza de que você mal pode esperar para ver algum código;)

Dê uma olhada nas declarações da API:

 // Creates a "Pseudo Console" (ConPTY). HRESULT WINAPI CreatePseudoConsole( _In_ COORD size, // ConPty Dimensions _In_ HANDLE hInput, // ConPty Input _In_ HANDLE hOutput, // ConPty Output _In_ DWORD dwFlags, // ConPty Flags _Out_ HPCON* phPC); // ConPty Reference // Resizes the given ConPTY to the specified size, in characters. HRESULT WINAPI ResizePseudoConsole(_In_ HPCON hPC, _In_ COORD size); // Closes the ConPTY and all associated handles. Client applications attached // to the ConPTY will also terminated. VOID WINAPI ClosePseudoConsole(_In_ HPCON hPC); 

A API ConPTY acima expõe essencialmente três novas funções para uso:

  • CreatePseudoConsole(size, hInput, hOutput, dwFlags, phPC)
    • Cria pty com dimensão em w colunas e linhas h , usando os canais criados pelo chamador:
      • size : largura e altura (em caracteres) do buffer ConPTY
      • hInput : para gravar dados de entrada em PTY como seqüências de texto / VT na codificação UTF-8
      • hOutput : para ler a saída do PTY como seqüências de texto / VT na codificação UTF-8
      • dwFlags : Valores possíveis:
        • PSEUDOCONSOLE_INHERIT_CURSOR : o ConPTY criado tentará herdar a posição do cursor do aplicativo de terminal pai
      • phPC : identificador de console para gerado por ConPty
    • Retorna : sucesso / fracasso. Se for bem-sucedido, o phPC contém o identificador para o novo ConPty

    ResizePseudoConsole(hPC, size)
    • Redimensiona o buffer interno do ConPTY para exibir uma largura e altura específicas

    ClosePseudoConsole (hPC)
    • ConPTY . , ConPTY, , ,

    ConPTY API


    ConPTY API ConPTY.

    : GitHub

      // Note: Most error checking removed for brevity. // ... // Initializes the specified startup info struct with the required properties and // updates its thread attribute list with the specified ConPTY handle HRESULT InitializeStartupInfoAttachedToConPTY(STARTUPINFOEX* siEx, HPCON hPC) { HRESULT hr = E_UNEXPECTED; size_t size; siEx->StartupInfo.cb = sizeof(STARTUPINFOEX); // Create the appropriately sized thread attribute list InitializeProcThreadAttributeList(NULL, 1, 0, &size); std::unique_ptr<BYTE[]> attrList = std::make_unique<BYTE[]>(size); // Set startup info's attribute list & initialize it siEx->lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>( attrList.get()); bool fSuccess = InitializeProcThreadAttributeList( siEx->lpAttributeList, 1, 0, (PSIZE_T)&size); if (fSuccess) { // Set thread attribute list's Pseudo Console to the specified ConPTY fSuccess = UpdateProcThreadAttribute( lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof(HPCON), NULL, NULL); return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError()); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; } // ... HANDLE hOut, hIn; HANDLE outPipeOurSide, inPipeOurSide; HANDLE outPipePseudoConsoleSide, inPipePseudoConsoleSide; HPCON hPC = 0; // Create the in/out pipes: CreatePipe(&inPipePseudoConsoleSide, &inPipeOurSide, NULL, 0); CreatePipe(&outPipeOurSide, &outPipePseudoConsoleSide, NULL, 0); // Create the Pseudo Console, using the pipes CreatePseudoConsole( {80, 32}, inPipePseudoConsoleSide, outPipePseudoConsoleSide, 0, &hPC); // Prepare the StartupInfoEx structure attached to the ConPTY. STARTUPINFOEX siEx{}; InitializeStartupInfoAttachedToConPTY(&siEx, hPC); // Create the client application, using startup info containing ConPTY info wchar_t* commandline = L"c:\\windows\\system32\\cmd.exe"; PROCESS_INFORMATION piClient{}; fSuccess = CreateProcessW( nullptr, commandline, nullptr, nullptr, TRUE, EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, &siEx->StartupInfo, &piClient); // ... 

    cmd.exe ConPTY, CreatePseudoConsole() . ConPTY / Cmd. ResizePseudoConsole() , — ClosePseudoConsole() .


    ConPTY :

     // Input "echo Hello, World!", press enter to have cmd process the command, // input an up arrow (to get the previous command), and enter again to execute. std::string helloWorld = "echo Hello, World!\n\x1b[A\n"; DWORD dwWritten; WriteFile(hIn, helloWorld.c_str(), (DWORD)helloWorld.length(), &dwWritten, nullptr); 


    , ConPTY:

     // Suppose some other async callback triggered us to resize. // This call will update the Terminal with the size we received. HRESULT hr = ResizePseudoConsole(hPC, {120, 30}); 


    ConPTY:

     ClosePseudoConsole(hPC); 

    : ConPTY ConHost .

    !


    ConPTY API — , , Windows … !

    ConPTY API Microsoft, Microsoft ( Windows Linux (WSL), Windows Containers, VSCode, Visual Studio .), , @ConEmuMaximus5ConEmu Windows.

    , ConPTY API.


    , : ConHost . Console API. , , .

    , VT, , — .

    , Windows, /VT UTF-8 Console API: « VT» , Console API (, 16M RGB True Color ).

    /


    / , ConPTY API: , , , , .

    VSCode ( GitHub #45693 ) , Windows.

    ConPTY API


    ConPTY API Windows 10 / 2018 .

    Windows, , , ConPTY. Win32 API, API Runtime Dynamic Linking LoadLibrary() GetProcAddress() .

    Windows ConPTY, API ConPTY. , , .

    , ?


    … ! , , ! : D

    , , , . — , Windows , .

    . Windows Console GitHub . , .

Source: https://habr.com/ru/post/pt420853/


All Articles