sources/Google.Solutions.Terminal/Controls/LocalShellClient.cs (58 lines of code) (raw):

// // Copyright 2024 Google LLC // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // using Google.Solutions.Platform.Dispatch; using Google.Solutions.Platform.IO; using System; using System.Diagnostics; using System.Threading.Tasks; namespace Google.Solutions.Terminal.Controls { /// <summary> /// Client for a local shell. /// </summary> public class LocalShellClient : PseudoTerminalClientBase { private IWin32Process? process = null; private readonly string shellProgram; public LocalShellClient(string shellProgram) { this.shellProgram = shellProgram; } protected override Task<IPseudoTerminal> ConnectCoreAsync( PseudoTerminalSize initialSize) { Debug.Assert(this.process == null); var processFactory = new Win32ProcessFactory(); this.process = processFactory.CreateProcessWithPseudoConsole( this.shellProgram, null, initialSize); // // The process is now attached to a pseudo-terminal, // but is still suspended. // Debug.Assert(this.process.PseudoTerminal != null); return Task.FromResult(this.process.PseudoTerminal!); } private void CloseProcess() { // // Close handle to process. // if (this.process != null) { this.process?.Dispose(); this.process = null; } } //--------------------------------------------------------------------- // Overrides. //--------------------------------------------------------------------- protected override void OnAfterConnect() { base.OnAfterConnect(); Debug.Assert(this.process != null); this.process!.Resume(); } protected override void OnConnectionClosed(DisconnectReason reason) { CloseProcess(); base.OnConnectionClosed(reason); } protected override void OnConnectionFailed(Exception e) { CloseProcess(); base.OnConnectionFailed(e); } protected override bool IsCausedByConnectionTimeout(Exception e) { // // No such thing as a connection timeout for a local process. // return false; } } }