Memenuhi Windows Pseudo Console (ConPTY)

Artikel yang diterbitkan 2 Agustus 2018

Ini adalah artikel kedua tentang baris perintah Windows, di mana kita akan membahas infrastruktur baru dan antarmuka pemrograman dari pseudo-console Windows, yaitu, Windows Pseudo Console (ConPTY): mengapa kita mengembangkannya, mengapa diperlukan, bagaimana cara kerjanya, cara menggunakannya, dan banyak lagi.

Dalam artikel terakhir “Warisan kuburan masa lalu. Masalah baris perintah Windows ” kami berbicara tentang prasyarat untuk munculnya terminal dan evolusi baris perintah di Windows, dan juga mulai mempelajari struktur internal Windows Console dan infrastruktur Windows Command-Line. Kami juga membahas banyak kelebihan dan kekurangan utama dari konsol Windows.

Salah satu kelemahannya adalah bahwa Windows berusaha untuk menjadi "berguna," tetapi itu mengganggu pengembang alternatif dan pihak ketiga, pengembang layanan, dll. Saat membuat konsol atau layanan, pengembang perlu memiliki akses ke saluran komunikasi di mana terminal / layanan mereka bertukar data dengan aplikasi baris perintah, atau menyediakan akses ke sana. Dalam dunia * NIX, ini bukan masalah karena * NIX menyediakan infrastruktur pseudo-terminal (PTY) yang membuatnya mudah untuk membuat saluran komunikasi untuk konsol atau layanan. Tetapi di Windows itu bukan ...

... sampai sekarang!

Dari TTY ke PTY


Sebelum menceritakan secara rinci tentang pengembangan kami, mari kita kembali sebentar ke pengembangan terminal.

Awalnya adalah TTY


Seperti dibahas dalam artikel sebelumnya , pada hari-hari awal komputasi, pengguna mengendalikan komputer menggunakan teletype elektromekanis (TTYs) yang terhubung ke komputer melalui beberapa jenis saluran komunikasi serial (biasanya melalui loop arus 20 mA ).


Ken Thompson dan Dennis Ritchie (berdiri) mengerjakan teletype DEC PDP-11 (pesan tanpa layar elektronik)

Distribusi Terminal


Teletype digantikan oleh terminal komputer dengan layar elektronik (biasanya layar CRT). Biasanya, terminal adalah perangkat yang sangat sederhana (karena itu istilah "terminal bisu"), hanya berisi barang elektronik dan daya pemrosesan yang diperlukan untuk tugas-tugas berikut:

  1. Penerimaan input teks dari keyboard.
  2. Buffer teks yang dimasukkan pada satu baris (termasuk pengeditan lokal sebelum mengirim).
  3. Mengirim / menerima teks pada saluran serial (biasanya melalui antarmuka RS-232 yang ada di mana - mana).
  4. Tampilan teks yang diterima pada tampilan terminal.

Terlepas dari kesederhanaannya (atau mungkin berkat itu), terminal dengan cepat menjadi sarana utama untuk mengelola minicomputer, mainframe dan server: sebagian besar operator entri data, operator komputer, administrator sistem, ilmuwan, peneliti, pengembang perangkat lunak, dan tokoh industri yang bekerja pada terminal DEC, IBM, Wyse dan banyak lainnya.


Laksamana Grace Hopper di kantornya dengan terminal DEC VT220 di mejanya

Distribusi terminal perangkat lunak


Sejak pertengahan 1980-an, alih-alih terminal khusus, komputer tujuan umum secara bertahap mulai digunakan, yang telah menjadi lebih terjangkau, populer dan kuat. Banyak PC awal dan komputer lain dari tahun 80-an memiliki aplikasi terminal yang membuka koneksi RS-232 ke PC dan bertukar data dengan siapa saja di ujung koneksi yang lain.

Ketika komputer serba guna menjadi lebih canggih, sebuah antarmuka pengguna grafis (GUI) dan dunia baru aplikasi bersamaan, termasuk aplikasi terminal, muncul.

Tetapi ada masalah: bagaimana aplikasi terminal berinteraksi dengan aplikasi command-line lain yang berjalan pada mesin yang sama? Dan bagaimana cara menghubungkan kabel serial secara fisik antara dua aplikasi yang berjalan di komputer yang sama?

Penampilan Terminal Pseudo (PTY)


Di dunia * NIX, masalahnya diselesaikan dengan memperkenalkan terminal semu (PTY) .

PTY mengemulasi peralatan telekomunikasi serial di komputer dengan memaparkan perangkat pseudo master dan slave (“master” dan “slave”): aplikasi terminal terhubung ke perangkat pseudo master, dan aplikasi baris perintah (misalnya, cangkang seperti cmd, PowerShell dan bash) terhubung ke perangkat pseudo-slave. Ketika klien terminal mentransmisikan teks dan / atau perintah kontrol (disandikan sebagai teks) ke perangkat master semu, teks diterjemahkan ke budak yang terkait dengannya. Teks dari aplikasi dikirim ke perangkat pseudo-budak, kemudian kembali ke master dan, dengan demikian, ke terminal. Data selalu dikirim / diterima secara tidak sinkron.


Aplikasi Terminal Pseudo / Shell

Penting untuk dicatat bahwa perangkat pseudo "slave" mengemulasi perilaku terminal fisik dan mengubah karakter perintah menjadi sinyal POSIX. Misalnya, jika pengguna memasukkan CTRL + C ke terminal, maka nilai ASCII untuk CTRL + C (0x03) dikirim melalui master. Ketika diterima pada perangkat pseudo-slave, nilai 0x03 dihapus dari aliran input dan sinyal SIGINT dihasilkan.

Infrastruktur PTY tersebut banyak digunakan oleh aplikasi terminal * NIX, manajer panel teks (mis. Layar, tmux), dll. Aplikasi ini memanggil openpty() , yang mengembalikan sepasang deskriptor file (fd) untuk master dan slave PTY. Kemudian aplikasi dapat memotong / mengeksekusi aplikasi command-line child (misalnya, bash), yang menggunakan slave fd untuk mendengarkan dan mengembalikan teks ke terminal yang terhubung.

Mekanisme ini memungkinkan aplikasi terminal untuk "berbicara" secara langsung dengan aplikasi baris perintah yang berjalan secara lokal, seperti terminal yang akan berbicara dengan komputer jarak jauh melalui koneksi serial / jaringan.

Apa, tidak ada konsol pseudo-konsol Windows?


Seperti yang kita bahas dalam artikel sebelumnya, sementara konsol Windows secara konseptual mirip dengan terminal * NIX tradisional, ia berbeda dalam beberapa cara utama, terutama pada tingkat terendah, yang dapat menyebabkan masalah bagi pengembang aplikasi baris perintah Windows, terminal / konsol pihak ketiga dan server aplikasi:

  1. Tidak ada infrastruktur PTY di Windows : ketika pengguna meluncurkan aplikasi baris perintah (misalnya, Cmd, PowerShell, wsl, ipconfig, dll.), Windows itu sendiri "menghubungkan" instance baru atau yang ada dari konsol ke aplikasi.
  2. Windows mengganggu konsol pihak ketiga dan aplikasi server : Windows (saat ini) tidak memberikan terminal cara untuk menyediakan saluran komunikasi di mana mereka ingin berinteraksi dengan aplikasi baris perintah. Terminal pihak ketiga harus membuat konsol dari layar, mengirim data yang dimasukkan pengguna di sana dan memo output dengan menggambar ulang pada tampilan konsol pihak ketiga sendiri!
  3. Hanya Windows yang memiliki API Konsol : Aplikasi baris perintah Windows mengandalkan Win32 Consol API, yang mengurangi portabilitas kode, karena semua platform lain mendukung teks / VT, bukan API.
  4. Akses jarak jauh non-standar : ketergantungan aplikasi baris perintah pada Consol API menyulitkan interaksi dan skrip akses jarak jauh.

Apa yang harus dilakukan


Banyak, banyak pengembang sering meminta mekanisme mirip PTY di Windows, terutama yang bekerja dengan ConEmu / Cmder, Console2 / ConsoleZ, Hyper, VSCode, Visual Studio, WSL, Docker, dan alat OpenSSH.

Bahkan Peter Bright, editor teknologi Ars Technica, meminta saya untuk menerapkan mekanisme PTY beberapa hari kemudian ketika saya mulai bekerja di tim Konsol:



Dan baru-baru ini lagi:



Akhirnya kami berhasil: kami membuat pseudo-console untuk Windows :

Selamat datang di Windows Pseudo Console (ConPTY)


Sejak pembentukan Tim Konsol sekitar empat tahun lalu, grup ini telah terlibat dalam perombakan konsol Windows dan mekanisme internal dari baris perintah. Pada saat yang sama, kami secara teratur dan hati-hati mempertimbangkan masalah yang dijelaskan di atas dan banyak masalah dan masalah terkait lainnya. Namun infrastruktur dan kode belum siap untuk memungkinkan rilis pseudo-console ... hingga sekarang!

Infrastruktur pseudo-console (ConPTY) Windows baru, API, dan beberapa perubahan terkait lainnya akan menghilangkan / mengurangi seluruh kelas masalah ... tanpa merusak kompatibilitas dengan aplikasi baris perintah yang ada !

Win32 ConPTY API baru (dokumentasi resmi akan segera diterbitkan) sekarang tersedia di build insider terbaru dari Windows 10 dan Windows 10 Insider Preview SDK yang sesuai . Mereka akan muncul dalam rilis besar berikutnya Windows 10 (di suatu tempat di musim gugur / musim dingin 2018).

Arsitektur Konsol / Konversi


Untuk memahami ConPTY, Anda perlu mempelajari arsitektur konsol Windows, atau lebih tepatnya ... ConHost!

Penting untuk dipahami bahwa meskipun ConHost mengimplementasikan semua yang Anda lihat dan ketahui sebagai aplikasi Windows Console, ConHost juga mengandung dan mengimplementasikan sebagian besar infrastruktur baris perintah Windows! Mulai sekarang, ConHost menjadi "simpul konsol" nyata , mendukung semua aplikasi baris perintah dan / atau aplikasi GUI yang berinteraksi dengan aplikasi baris perintah!

Bagaimana? Mengapa Apa? Mari kita lihat lebih dekat.

Berikut ini adalah tampilan tingkat tinggi dari arsitektur konsol internal / ConHost:



Dibandingkan dengan arsitektur dari artikel sebelumnya , ConHost sekarang berisi beberapa modul tambahan untuk pemrosesan VT dan modul ConPTY baru yang mengimplementasikan API terbuka:

  • ConPTY API : Win32 ConPTY APIs baru menyediakan mekanisme yang mirip dengan model POSIX PTY, tetapi dalam pembiasan Windows.
  • Interaktivitas VT : menerima teks input dalam pengkodean UTF-8, mengubah setiap karakter teks yang ditampilkan menjadi catatan INPUT_RECORD sesuai dan menyimpannya dalam buffer input. Itu juga memproses urutan melarikan diri, seperti 0x03 (CTRL + C), mengubahnya menjadi KEY_EVENT_RECORDS , yang menghasilkan tindakan melarikan diri yang sesuai.
  • VT Renderer : Menghasilkan urutan VT yang diperlukan untuk memindahkan kursor dan merender teks dan gaya di bidang buffer output yang telah berubah dari frame sebelumnya.

OK, tapi apa artinya itu?

Bagaimana cara kerja aplikasi baris perintah Windows?


Untuk lebih memahami dampak dari infrastruktur ConPTY yang baru, mari kita lihat bagaimana konsol Windows dan aplikasi command-line sejauh ini berfungsi.

Setiap kali pengguna meluncurkan aplikasi baris perintah seperti Cmd, PowerShell atau ssh, Windows menciptakan proses Win32 baru di mana ia memuat biner aplikasi yang dapat dieksekusi dan setiap dependensi (sumber daya atau perpustakaan).

Proses yang baru dibuat biasanya mewarisi stdin dan deskriptor stdout dari induknya. Jika proses induk adalah proses Windows GUI, maka deskriptor stdin dan stdout hilang, sehingga Windows akan menggunakan dan melampirkan aplikasi baru ke instance konsol baru. Komunikasi antara aplikasi baris perintah dan konsolnya dikirimkan melalui ConDrv.

Sebagai contoh, jika Anda menjalankan dari instance PowerShell tanpa hak yang lebih tinggi, proses aplikasi baru akan mewarisi stdin / stdout deskriptor induk dan, oleh karena itu, menerima data input dan output output ke konsol yang sama dengan induk.

Di sini kita perlu membuat reservasi, karena dalam beberapa kasus aplikasi baris perintah diluncurkan terpasang ke instance baru konsol, terutama untuk alasan keamanan, tetapi deskripsi di atas biasanya benar.

Pada akhirnya, ketika aplikasi command-line / shell dijalankan, Windows menghubungkannya ke instance konsol (ConHost.exe) melalui ConDrv:



Bagaimana cara kerja ConHost?


Setiap kali aplikasi baris perintah dijalankan, Windows menghubungkan aplikasi ke instance baru atau yang sudah ada dari ConHost. Aplikasi dan instance konsolnya terhubung melalui driver konsol mode-kernel (ConDrv), yang mengirim / menerima pesan IOCTL yang berisi permintaan panggilan API serial dan / atau data teks.

Secara historis, seperti yang dinyatakan dalam artikel sebelumnya, pekerjaan ConHost relatif sederhana saat ini:

  • Pengguna menghasilkan input dari keyboard / mouse / pena / touchpad, yang dikonversi menjadi KEY_EVENT_RECORD atau MOUSE_EVENT_RECORD dan disimpan dalam buffer input.
  • Buffer input dikosongkan satu catatan pada satu waktu, melakukan tindakan input yang diminta, seperti menampilkan teks pada layar, memindahkan kursor, menyalin / menempelkan teks, dll. Banyak dari tindakan ini mengubah isi buffer output. Area yang diubah ini direkam oleh engine status ConHost.
  • Di setiap frame, konsol menampilkan area yang berubah dari buffer output.

Saat aplikasi baris perintah memanggil Windows Console API, panggilan API diserialisasi ke dalam pesan IOCTL dan dikirim melalui driver ConDrv. Kemudian mengirimkan pesan IOCTL ke konsol terlampir, yang menerjemahkan dan mengeksekusi panggilan API yang diminta. Nilai-nilai yang dikembalikan / keluaran diserialisasi kembali ke pesan IOCTL dan dikirim kembali ke aplikasi melalui ConDrv.

ConHost: Berkontribusi ke Masa Lalu untuk Masa Depan


Microsoft berupaya untuk menjaga kompatibilitas ke belakang dengan aplikasi dan alat yang ada bila memungkinkan. Khusus untuk baris perintah. Faktanya, Windows 10 versi 32-bit masih dapat menjalankan banyak / sebagian besar aplikasi Win16 dan executable!

Seperti disebutkan di atas, salah satu peran utama ConHost adalah menyediakan layanan untuk aplikasi baris perintahnya, terutama aplikasi lawas yang menjalankan dan mengandalkan API konsol Win32. Sekarang ConHost menawarkan layanan baru:

  • Infrastruktur mirip PTY yang mulus untuk komunikasi dengan konsol dan terminal modern
  • Memutakhirkan aplikasi warisan / perintah tradisional
    • Menerima dan mengonversi teks / VT UTF-8 untuk memasukkan rekaman (seolah-olah dimasukkan oleh pengguna)
    • API Konsol memanggil aplikasi yang dihosting, memperbarui buffer outputnya sesuai
    • Menampilkan area yang dimodifikasi dari buffer output dalam pengkodean UTF-8, teks / VT

Berikut ini adalah contoh bagaimana aplikasi konsol modern berkomunikasi dengan aplikasi baris perintah melalui ConPTY ConHost.



Dalam model baru ini:

  1. Konsol:
    1. Membuat saluran komunikasi sendiri
    2. Memanggil ConPTY API untuk membuat ConPTY, memaksa Windows untuk menjalankan instance ConHost yang terhubung ke ujung saluran lainnya
    3. Membuat instance aplikasi baris perintah (mis. PowerShell) yang terhubung ke ConHost, seperti biasa
  2. Conhost:
    1. Membaca teks UTF-8 / VT pada input dan mengubahnya menjadi catatan INPUT_RECORD , yang dikirim ke aplikasi baris perintah
    2. Lakukan panggilan API dari aplikasi baris perintah yang dapat mengubah konten buffer output
    3. Menampilkan perubahan buffer output dalam pengkodean UTF-8 (teks / VT) dan mengirim teks yang diterima ke konsolnya
  3. Aplikasi baris perintah:
    1. Ini berfungsi seperti biasa, membaca input dan memanggil API Konsol, tidak tahu bahwa ConPTY ConHost menerjemahkan input dan output dari / ke UTF-8!

Momen terakhir itu penting! Ketika aplikasi baris perintah yang lama menggunakan panggilan ke API Konsol seperti WriteConsoleOutput(...) , teks yang ditentukan ditulis ke buffer output ConHost yang sesuai. Secara berkala, ConHost menampilkan area yang berubah dari buffer output sebagai teks / VT, yang dikirim melalui stdout kembali ke konsol.

Pada akhirnya, bahkan aplikasi baris perintah tradisional dari luar "berbicara" teks / VT tanpa perubahan apa pun !

Menggunakan infrastruktur ConPTY yang baru, konsol pihak ketiga sekarang dapat secara langsung berinteraksi dengan aplikasi baris perintah modern dan tradisional dan menukar semuanya dalam teks / VT.

Secara jarak jauh berinteraksi dengan aplikasi baris perintah Windows


Mekanisme yang dijelaskan di atas berfungsi dengan baik di satu komputer, tetapi juga membantu ketika berinteraksi, misalnya, dengan contoh PowerShell di komputer Windows jarak jauh atau dalam wadah.

Ada masalah saat memulai aplikasi baris perintah dari jarak jauh (mis. Pada komputer, server, atau wadah jarak jauh). Faktanya adalah bahwa aplikasi baris perintah pada mesin jarak jauh berkomunikasi dengan instance ConHost lokal, karena pesan IOCTL tidak dirancang untuk ditransmisikan melalui jaringan. Bagaimana cara mentransfer input dari konsol lokal ke mesin jarak jauh dan bagaimana cara mendapatkan output dari aplikasi yang berjalan di sana? Selain itu, apa yang harus dilakukan dengan mesin Mac dan Linux, di mana ada terminal tetapi tidak ada konsol yang kompatibel dengan Windows?

Jadi, untuk mengontrol mesin Windows dari jarak jauh, kita membutuhkan semacam perantara komunikasi yang dapat secara transparan membuat serialisasi data melalui jaringan, mengatur masa pakai instance aplikasi, dll.

Mungkin sesuatu seperti ssh ?

Untungnya, OpenSSH baru - baru ini porting ke Windows dan ditambahkan sebagai opsi tambahan untuk Windows 10 . PowerShell Core juga menggunakan ssh sebagai salah satu protokol remoting PowerShell Core Remoting yang didukung. Dan bagi mereka yang menjalankan Windows PowerShell, remoting Windows PowerShell Remoting masih merupakan opsi yang dapat diterima.

Mari kita lihat bagaimana OpenSSH untuk Windows sekarang memungkinkan Anda untuk mengontrol aplikasi Windows dan perintah-perintah dari jarak jauh:



OpenSSH saat ini mencakup beberapa komplikasi yang tidak diinginkan:

  1. Pengguna:
    1. Mulai klien ssh, dan Windows menghubungkan instance konsol seperti biasa
    2. Masukkan teks ke konsol, yang mengirim penekanan tombol ke klien ssh
  2. klien ssh:
    1. Membaca input sebagai byte data teks
    2. Mengirim data teks melalui jaringan ke layanan mendengarkan sshd
  3. Layanan sshd melewati beberapa tahap:
    1. Meluncurkan shell default (misalnya, Cmd), yang memaksa Windows untuk membuat dan menghubungkan instance konsol baru
    2. Menemukan dan menghubungkan ke konsol instance CDM
    3. Memindahkan konsol dari layar (dan / atau menyembunyikannya)
    4. Mengirim input yang diterima dari ssh client ke konsol dari layar sebagai input
  4. Contoh cmd berfungsi seperti biasa:
    1. Mengumpulkan input dari layanan sshd
    2. Apakah berhasil
    3. Memanggil API Konsol untuk merender / gaya teks, memindahkan kursor, dll.
  5. Konsol [off-screen] terlampir:
    1. Lakukan panggilan API dengan memperbarui buffer output.
  6. Layanan sshd:
    1. Memotong buffer output konsol luar layar, menemukan perbedaannya, menyandikannya ke dalam teks / VT dan mengirimkan kembali ...
  7. Klien ssh yang mengirim teks ...
  8. Konsol yang menampilkan teks

Menyenangkan bukan? Tidak semuanya! Dalam situasi ini, banyak yang bisa serba salah, terutama dalam proses mensimulasikan dan mengirim input pengguna dan membilas buffer output dari konsol di luar layar. Hal ini menyebabkan ketidakstabilan, kerusakan, kerusakan data, konsumsi energi yang berlebihan, dll. Selain itu, tidak semua aplikasi melakukan pekerjaan menghapus tidak hanya teks itu sendiri, tetapi juga propertinya, itulah sebabnya pemformatan dan warna hilang!

Pekerjaan jarak jauh menggunakan ConHost dan ConPTY modern


Tentunya kita dapat memperbaiki situasi? Ya, tentu saja kita bisa - mari kita buat beberapa perubahan arsitektur dan terapkan ConPTY baru kita:



Diagram menunjukkan bahwa rangkaian telah berubah sebagai berikut:

  1. Pengguna:
    1. Mulai klien ssh, dan Windows menghubungkan instance konsol seperti biasa
    2. Masukkan teks ke konsol, yang mengirim penekanan tombol ke klien ssh
  2. klien ssh:
    1. Membaca input sebagai byte data teks
    2. Mengirim data teks melalui jaringan ke layanan mendengarkan sshd
  3. Layanan sshd:
    1. Membuat saluran stdin / stdout
    2. Memanggil API ConPTY untuk memulai ConPTY
    3. Mulai instance Cmd yang terhubung ke ujung ConPTY lainnya. Windows memulai dan memasang instance baru dari ConHost
  4. Contoh cmd berfungsi seperti biasa:
    1. Mengumpulkan input dari layanan sshd
    2. Apakah berhasil
    3. Memanggil API Konsol untuk merender / gaya teks, memindahkan kursor, dll.
  5. Instance ConPTY ConHost:
    1. Lakukan panggilan API dengan memperbarui buffer output.
    2. Menampilkan wilayah yang berubah dari buffer output sebagai teks / VT berkode UTF-8, yang dikirim kembali ke konsol / terminal melalui ssh

Pendekatan ini menggunakan ConPTY jelas lebih bersih dan sederhana untuk layanan sshd. Panggilan ke Windows Console API dibuat seluruhnya dalam contoh ConHost dari aplikasi baris perintah, yang mengubah semua perubahan yang terlihat menjadi teks / VT. Siapa pun yang terhubung ke ConHost, ia tidak perlu tahu bahwa aplikasi di sana memanggil API Konsol, dan tidak menghasilkan teks / VT!

Setuju bahwa mekanisme remoting ConPTY baru ini mengarah pada arsitektur yang elegan, konsisten, dan sederhana. Dikombinasikan dengan fitur-fitur canggih yang tertanam dalam ConHost, dukungan untuk aplikasi yang lebih lama dan menampilkan perubahan dari aplikasi yang memanggil konsol konsol API sebagai teks / VT, infrastruktur ConHost dan ConPTY baru membantu kita memindahkan masa lalu ke masa depan.

API KONPTI dan cara menggunakannya


API ConPTY tersedia dalam versi SDK Windows 10 Insider Preview saat ini .

Sekarang, saya yakin Anda tidak sabar untuk melihat beberapa kode;)

Lihatlah deklarasi 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); 

API ConPTY di atas pada dasarnya memaparkan tiga fungsi baru untuk digunakan:

  • CreatePseudoConsole(size, hInput, hOutput, dwFlags, phPC)
    • Membuat pty dengan dimensi di kolom w dan garis h , menggunakan saluran yang dibuat oleh pemanggil:
      • size : lebar dan tinggi (dalam karakter) dari buffer ConPTY
      • hInput : untuk menulis data input ke PTY sebagai urutan teks / VT dalam pengkodean UTF-8
      • hOutput : untuk membaca output dari PTY sebagai urutan teks / VT dalam pengkodean UTF-8
      • dwFlags : Nilai yang memungkinkan:
        • PSEUDOCONSOLE_INHERIT_CURSOR: ConPTY yang dibuat akan mencoba mewarisi posisi kursor dari aplikasi terminal induk
      • phPC : handle konsol untuk dihasilkan oleh ConPty
    • Pengembalian : sukses / gagal. Jika berhasil, phPC berisi pegangan ke ConPty baru

    ResizePseudoConsole(hPC, size)
    • Mengubah ukuran buffer ConPTY internal untuk menampilkan lebar dan tinggi tertentu

    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/id420853/


All Articles