MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#nullable enable5 6using System.Diagnostics;7using System.IO;8using System.Threading;9using System.Threading.Tasks;10using Microsoft.PowerShell.Telemetry;11 12namespace System.Management.Automation;13 14/// <summary>15/// Represents a lazily retrieved <see cref="Stream" /> for transfering bytes16/// to or from.17/// </summary>18internal abstract class BytePipe19{20 public abstract Task<Stream> GetStream(CancellationToken cancellationToken);21 22 internal AsyncByteStreamTransfer Bind(BytePipe bytePipe)23 {24 Debug.Assert(bytePipe is not null);25 return new AsyncByteStreamTransfer(bytePipe, destinationPipe: this);26 }27}28 29/// <summary>30/// Represents a <see cref="Stream" /> lazily retrieved from the underlying31/// <see cref="NativeCommandProcessor" />.32/// </summary>33internal sealed class NativeCommandProcessorBytePipe : BytePipe34{35 private readonly NativeCommandProcessor _nativeCommand;36 37 private readonly bool _stdout;38 39 internal NativeCommandProcessorBytePipe(40 NativeCommandProcessor nativeCommand,41 bool stdout)42 {43 Debug.Assert(nativeCommand is not null);44 _nativeCommand = nativeCommand;45 _stdout = stdout;46 }47 48 public override async Task<Stream> GetStream(CancellationToken cancellationToken)49 {50 // If the native command we're wrapping is the upstream command then51 // NativeCommandProcessor.Prepare will have already been called before52 // the creation of this BytePipe.53 if (_stdout)54 {55 return _nativeCommand.GetStream(stdout: true);56 }57 58 await _nativeCommand.WaitForProcessInitializationAsync(cancellationToken);59 return _nativeCommand.GetStream(stdout: false);60 }61}62 63/// <summary>64/// Provides an byte pipe implementation representing a <see cref="FileStream" />.65/// </summary>66internal sealed class FileBytePipe : BytePipe67{68 private readonly Stream _stream;69 70 private FileBytePipe(Stream stream)71 {72 Debug.Assert(stream is not null);73 _stream = stream;74 }75 76 internal static FileBytePipe Create(string fileName, bool append)77 {78 FileStream fileStream;79 try80 {81 PathUtils.MasterStreamOpen(82 fileName,83 resolvedEncoding: null,84 defaultEncoding: false,85 append,86 Force: true,87 NoClobber: false,88 out fileStream,89 streamWriter: out _,90 readOnlyFileInfo: out _,91 isLiteralPath: true);92 }93 catch (Exception e) when (e.Data.Contains(typeof(ErrorRecord)))94 {95 // The error record is attached to the exception when thrown to preserve96 // the call stack.97 ErrorRecord? errorRecord = e.Data[typeof(ErrorRecord)] as ErrorRecord;98 if (errorRecord is null)99 {100 throw;101 }102 103 e.Data.Remove(typeof(ErrorRecord));104 throw new RuntimeException(null, e, errorRecord);105 }106 107 ApplicationInsightsTelemetry.SendExperimentalUseData("PSNativeCommandPreserveBytePipe", "f");108 109 return new FileBytePipe(fileStream);110 }111 112 public override Task<Stream> GetStream(CancellationToken cancellationToken) => Task.FromResult(_stream);113}114 