mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 18:43:54 -06:00
implement dispose pattern
- Full Dispose Pattern for ProcessResources since it has unmanaged resources - Basic Dispose Pattern for PseudoConsolePipe since it has managed resources - Fix naming of iStdOut to hStdOut - Change parameter order of Process.Start to make more sense
This commit is contained in:
parent
637c57473e
commit
bf32b8d48f
@ -21,9 +21,6 @@ namespace MiniTerm.Native
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern int CreatePseudoConsole(COORD size, SafeFileHandle hInput, SafeFileHandle hOutput, uint dwFlags, out IntPtr phPC);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern int CreatePseudoConsole(COORD size, IntPtr hInput, IntPtr hOutput, uint dwFlags, out IntPtr phPC);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern int ResizePseudoConsole(IntPtr hPC, COORD size);
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static MiniTerm.Native.ProcessApi;
|
||||
using static MiniTerm.Native.PseudoConsoleApi;
|
||||
|
||||
namespace MiniTerm
|
||||
{
|
||||
@ -15,7 +16,7 @@ namespace MiniTerm
|
||||
/// <summary>
|
||||
/// Start and configure a process. The return value should be considered opaque, and eventually disposed.
|
||||
/// </summary>
|
||||
internal static ProcessResources Start(IntPtr hPC, string command, IntPtr attributes)
|
||||
internal static ProcessResources Start(string command, IntPtr attributes, IntPtr hPC)
|
||||
{
|
||||
var startupInfo = ConfigureProcessThread(hPC, attributes);
|
||||
var processInfo = RunProcess(ref startupInfo, "cmd.exe");
|
||||
@ -93,26 +94,6 @@ namespace MiniTerm
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
private static void CleanUp(STARTUPINFOEX startupInfo, PROCESS_INFORMATION processInfo)
|
||||
{
|
||||
// Free the attribute list
|
||||
if (startupInfo.lpAttributeList != IntPtr.Zero)
|
||||
{
|
||||
DeleteProcThreadAttributeList(startupInfo.lpAttributeList);
|
||||
Marshal.FreeHGlobal(startupInfo.lpAttributeList);
|
||||
}
|
||||
|
||||
// Close process and thread handles
|
||||
if (processInfo.hProcess != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(processInfo.hProcess);
|
||||
}
|
||||
if (processInfo.hThread != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(processInfo.hThread);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ProcessResources : IDisposable
|
||||
{
|
||||
public ProcessResources(STARTUPINFOEX startupInfo, PROCESS_INFORMATION processInfo)
|
||||
@ -124,10 +105,58 @@ namespace MiniTerm
|
||||
STARTUPINFOEX StartupInfo { get; }
|
||||
PROCESS_INFORMATION ProcessInfo { get; }
|
||||
|
||||
#region IDisposable Support
|
||||
|
||||
private bool disposedValue = false; // To detect redundant calls
|
||||
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// dispose managed state (managed objects).
|
||||
}
|
||||
|
||||
// dispose unmanaged state
|
||||
|
||||
// Free the attribute list
|
||||
if (StartupInfo.lpAttributeList != IntPtr.Zero)
|
||||
{
|
||||
DeleteProcThreadAttributeList(StartupInfo.lpAttributeList);
|
||||
Marshal.FreeHGlobal(StartupInfo.lpAttributeList);
|
||||
}
|
||||
|
||||
// Close process and thread handles
|
||||
if (ProcessInfo.hProcess != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(ProcessInfo.hProcess);
|
||||
}
|
||||
if (ProcessInfo.hThread != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(ProcessInfo.hThread);
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
~ProcessResources()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
// This code added to correctly implement the disposable pattern.
|
||||
public void Dispose()
|
||||
{
|
||||
CleanUp(StartupInfo, ProcessInfo);
|
||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
Dispose(true);
|
||||
// use the following line if the finalizer is overridden above.
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,10 +24,23 @@ namespace MiniTerm
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
ReadSide?.Dispose();
|
||||
WriteSide?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReadSide.Dispose();
|
||||
WriteSide.Dispose();
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,14 +26,14 @@ namespace MiniTerm
|
||||
/// </summary>
|
||||
private static void EnableVirtualTerminalSequenceProcessing()
|
||||
{
|
||||
var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (!GetConsoleMode(iStdOut, out uint outConsoleMode))
|
||||
var hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (!GetConsoleMode(hStdOut, out uint outConsoleMode))
|
||||
{
|
||||
throw new InvalidOperationException("Could not get console mode");
|
||||
}
|
||||
|
||||
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
|
||||
if (!SetConsoleMode(iStdOut, outConsoleMode))
|
||||
if (!SetConsoleMode(hStdOut, outConsoleMode))
|
||||
{
|
||||
throw new InvalidOperationException("Could not enable virtual terminal processing");
|
||||
}
|
||||
@ -48,8 +48,8 @@ namespace MiniTerm
|
||||
{
|
||||
using (var inputPipe = new PseudoConsolePipe())
|
||||
using (var outputPipe = new PseudoConsolePipe())
|
||||
using (var pseudoConsole = PseudoConsole.Create(inputPipe.ReadSide, outputPipe.WriteSide, Console.WindowWidth, Console.WindowHeight))
|
||||
using (var process = Process.Start(pseudoConsole.Handle, command, PseudoConsole.PseudoConsoleThreadAttribute))
|
||||
using (var pseudoConsole = PseudoConsole.Create(inputPipe.ReadSide, outputPipe.WriteSide, (short)Console.WindowWidth, (short)Console.WindowHeight))
|
||||
using (var process = Process.Start(command, PseudoConsole.PseudoConsoleThreadAttribute, pseudoConsole.Handle))
|
||||
{
|
||||
// set up a background task to copy all pseudoconsole output to stdout
|
||||
Task.Run(() => CopyPipeToOutput(outputPipe.ReadSide));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user