Add an example application that uses the pseudoconsole APIs (#247)
This sample implements a simple "Echo Console" that illustrates the mechanism by which a caller can directly invoke & communicate with Command-Line applications. 1. Creates two pipes - one for output, the second for output 1. Creates a Pseudo Console attached to the other end of the pipes 1. Creates a child process (an instance of `ping.exe` in this case), attached to the Pseudo Console 1. Creates a thread that reads the input pipe, displaying received text on the screen
This commit is contained in:
parent
da53ff957f
commit
ac843745fa
36
samples/ConPTY/EchoCon/EchoCon.sln
Normal file
36
samples/ConPTY/EchoCon/EchoCon.sln
Normal file
|
@ -0,0 +1,36 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27703.2026
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EchoCon", "EchoCon\EchoCon.vcxproj", "{96274800-9574-423E-892A-909FBE2AC8BE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{556CAA54-33E0-4F99-95C8-0DFD6E8F6C6B}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
readme.md = readme.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Debug|x64.Build.0 = Debug|x64
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Debug|x86.Build.0 = Debug|Win32
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Release|x64.ActiveCfg = Release|x64
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Release|x64.Build.0 = Release|x64
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Release|x86.ActiveCfg = Release|Win32
|
||||
{96274800-9574-423E-892A-909FBE2AC8BE}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B27C5007-61E2-4080-965D-8C934367BA4F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
189
samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp
Normal file
189
samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
// EchoCon.cpp : Entry point for the EchoCon Pseudo-Consle sample application.
|
||||
// Copyright © 2018, Microsoft
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <Windows.h>
|
||||
#include <process.h>
|
||||
|
||||
// Forward declarations
|
||||
HRESULT CreatePseudoConsoleAndPipes(HPCON*, HANDLE*, HANDLE*);
|
||||
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX*, HPCON);
|
||||
void __cdecl PipeListener(LPVOID);
|
||||
|
||||
int main()
|
||||
{
|
||||
wchar_t szCommand[]{ L"ping localhost" };
|
||||
HRESULT hr{ E_UNEXPECTED };
|
||||
HANDLE hConsole = { GetStdHandle(STD_OUTPUT_HANDLE) };
|
||||
|
||||
// Enable Console VT Processing
|
||||
DWORD consoleMode{};
|
||||
GetConsoleMode(hConsole, &consoleMode);
|
||||
hr = SetConsoleMode(hConsole, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
? S_OK
|
||||
: GetLastError();
|
||||
if (S_OK == hr)
|
||||
{
|
||||
HPCON hPC{ INVALID_HANDLE_VALUE };
|
||||
|
||||
// Create the Pseudo Console and pipes to it
|
||||
HANDLE hPipeIn{ INVALID_HANDLE_VALUE };
|
||||
HANDLE hPipeOut{ INVALID_HANDLE_VALUE };
|
||||
hr = CreatePseudoConsoleAndPipes(&hPC, &hPipeIn, &hPipeOut);
|
||||
if (S_OK == hr)
|
||||
{
|
||||
// Create & start thread to listen to the incoming pipe
|
||||
// Note: Using CRT-safe _beginthread() rather than CreateThread()
|
||||
HANDLE hPipeListenerThread{ reinterpret_cast<HANDLE>(_beginthread(PipeListener, 0, hPipeIn)) };
|
||||
|
||||
// Initialize the necessary startup info struct
|
||||
STARTUPINFOEX startupInfo{};
|
||||
if (S_OK == InitializeStartupInfoAttachedToPseudoConsole(&startupInfo, hPC))
|
||||
{
|
||||
// Launch ping to emit some text back via the pipe
|
||||
PROCESS_INFORMATION piClient{};
|
||||
hr = CreateProcess(
|
||||
NULL, // No module name - use Command Line
|
||||
szCommand, // Command Line
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
FALSE, // Inherit handles
|
||||
EXTENDED_STARTUPINFO_PRESENT, // Creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&startupInfo.StartupInfo, // Pointer to STARTUPINFO
|
||||
&piClient) // Pointer to PROCESS_INFORMATION
|
||||
? S_OK
|
||||
: GetLastError();
|
||||
|
||||
if (S_OK == hr)
|
||||
{
|
||||
// Wait up to 10s for ping process to complete
|
||||
WaitForSingleObject(piClient.hThread, 10 * 1000);
|
||||
|
||||
// Allow listening thread to catch-up with final output!
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
// --- CLOSEDOWN ---
|
||||
|
||||
// Now safe to clean-up client app's process-info & thread
|
||||
CloseHandle(piClient.hThread);
|
||||
CloseHandle(piClient.hProcess);
|
||||
|
||||
// Cleanup attribute list
|
||||
DeleteProcThreadAttributeList(startupInfo.lpAttributeList);
|
||||
free(startupInfo.lpAttributeList);
|
||||
}
|
||||
|
||||
// Close ConPTY - this will terminate client process if running
|
||||
ClosePseudoConsole(hPC);
|
||||
|
||||
// Clean-up the pipes
|
||||
if (INVALID_HANDLE_VALUE != hPipeOut) CloseHandle(hPipeOut);
|
||||
if (INVALID_HANDLE_VALUE != hPipeIn) CloseHandle(hPipeIn);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK == hr ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
HRESULT CreatePseudoConsoleAndPipes(HPCON* phPC, HANDLE* phPipeIn, HANDLE* phPipeOut)
|
||||
{
|
||||
HRESULT hr{ E_UNEXPECTED };
|
||||
HANDLE hPipePTYIn{ INVALID_HANDLE_VALUE };
|
||||
HANDLE hPipePTYOut{ INVALID_HANDLE_VALUE };
|
||||
|
||||
// Create the pipes to which the ConPTY will connect
|
||||
if (CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) &&
|
||||
CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0))
|
||||
{
|
||||
// Determine required size of Pseudo Console
|
||||
COORD consoleSize{};
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi{};
|
||||
HANDLE hConsole{ GetStdHandle(STD_OUTPUT_HANDLE) };
|
||||
if (GetConsoleScreenBufferInfo(hConsole, &csbi))
|
||||
{
|
||||
consoleSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
consoleSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
}
|
||||
|
||||
// Create the Pseudo Console of the required size, attached to the PTY-end of the pipes
|
||||
hr = CreatePseudoConsole(consoleSize, hPipePTYIn, hPipePTYOut, 0, phPC);
|
||||
|
||||
// Note: We can close the handles to the PTY-end of the pipes here
|
||||
// because the handles are dup'ed into the ConHost and will be released
|
||||
// when the ConPTY is destroyed.
|
||||
if (INVALID_HANDLE_VALUE != hPipePTYOut) CloseHandle(hPipePTYOut);
|
||||
if (INVALID_HANDLE_VALUE != hPipePTYIn) CloseHandle(hPipePTYIn);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Initializes the specified startup info struct with the required properties and
|
||||
// updates its thread attribute list with the specified ConPTY handle
|
||||
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX* pStartupInfo, HPCON hPC)
|
||||
{
|
||||
HRESULT hr{ E_UNEXPECTED };
|
||||
|
||||
if (pStartupInfo)
|
||||
{
|
||||
size_t attrListSize{};
|
||||
|
||||
pStartupInfo->StartupInfo.cb = sizeof(STARTUPINFOEX);
|
||||
|
||||
// Get the size of the thread attribute list.
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &attrListSize);
|
||||
|
||||
// Allocate a thread attribute list of the correct size
|
||||
pStartupInfo->lpAttributeList =
|
||||
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(attrListSize));
|
||||
|
||||
// Initialize thread attribute list
|
||||
if (pStartupInfo->lpAttributeList
|
||||
&& InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize))
|
||||
{
|
||||
// Set Pseudo Console attribute
|
||||
hr = UpdateProcThreadAttribute(
|
||||
pStartupInfo->lpAttributeList,
|
||||
0,
|
||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
||||
hPC,
|
||||
sizeof(HPCON),
|
||||
NULL,
|
||||
NULL)
|
||||
? S_OK
|
||||
: HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void __cdecl PipeListener(LPVOID pipe)
|
||||
{
|
||||
HANDLE hPipe{ pipe };
|
||||
HANDLE hConsole{ GetStdHandle(STD_OUTPUT_HANDLE) };
|
||||
|
||||
const DWORD BUFF_SIZE{ 512 };
|
||||
char szBuffer[BUFF_SIZE]{};
|
||||
|
||||
DWORD dwBytesWritten{};
|
||||
DWORD dwBytesRead{};
|
||||
BOOL fRead{ FALSE };
|
||||
do
|
||||
{
|
||||
// Read from the pipe
|
||||
fRead = ReadFile(hPipe, szBuffer, BUFF_SIZE, &dwBytesRead, NULL);
|
||||
|
||||
// Write received text to the Console
|
||||
// Note: Write to the Console using WriteFile(hConsole...), not printf()/puts() to
|
||||
// prevent partially-read VT sequences from corrupting output
|
||||
WriteFile(hConsole, szBuffer, dwBytesRead, &dwBytesWritten, NULL);
|
||||
|
||||
} while (fRead && dwBytesRead >= 0);
|
||||
}
|
165
samples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj
Normal file
165
samples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj
Normal file
|
@ -0,0 +1,165 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>EchoCon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17738.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EchoCon.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
33
samples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters
Normal file
33
samples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EchoCon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
8
samples/ConPTY/EchoCon/EchoCon/stdafx.cpp
Normal file
8
samples/ConPTY/EchoCon/EchoCon/stdafx.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// EchoCon.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
13
samples/ConPTY/EchoCon/EchoCon/stdafx.h
Normal file
13
samples/ConPTY/EchoCon/EchoCon/stdafx.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
8
samples/ConPTY/EchoCon/EchoCon/targetver.h
Normal file
8
samples/ConPTY/EchoCon/EchoCon/targetver.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
34
samples/ConPTY/EchoCon/readme.md
Normal file
34
samples/ConPTY/EchoCon/readme.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
# "EchoCon" ConPTY Sample App
|
||||
This is a very simple sample application that illustrates how to use the new Win32 Pseudo Console
|
||||
(ConPTY) by:
|
||||
|
||||
1. Creating an input and an output pipe
|
||||
1. Calling `CreatePseudoConsole()` to create a ConPTY instance attached to the other end of the pipes
|
||||
1. Spawning an instance of `ping.exe` connected to the ConPTY
|
||||
1. Running a thread that listens for output from ping.exe, writing received text to the Console
|
||||
|
||||
# Pre-Requirements
|
||||
To build and run this sample, you must install:
|
||||
* Windows 10 Insider build 17733 or later
|
||||
* [Latest Windows 10 Insider SDK](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewSDK)
|
||||
|
||||
# Running the sample
|
||||
Once successfully built, running EchoCon should clear the screen and display the results of the
|
||||
echo command:
|
||||
|
||||
```
|
||||
Pinging Rincewind [::1] with 32 bytes of data:
|
||||
Reply from ::1: time<1ms
|
||||
Reply from ::1: time<1ms
|
||||
Reply from ::1: time<1ms
|
||||
Reply from ::1: time<1ms
|
||||
|
||||
Ping statistics for ::1:
|
||||
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
|
||||
Approximate round trip times in milli-seconds:
|
||||
Minimum = 0ms, Maximum = 0ms, Average = 0ms
|
||||
```
|
||||
|
||||
# Resources
|
||||
For more information on the new Pseudo Console infrastructure and API, please review
|
||||
[this blog post](https://blogs.msdn.microsoft.com/commandline/2018/08/02/windows-command-line-introducing-the-windows-pseudo-console-conpty/)
|
Loading…
Reference in a new issue