Skip to content

Commit

Permalink
Fix 'Sequence contains no elements' bug (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
webbertakken authored Oct 7, 2020
1 parent c64e60b commit ec978d7
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 54 deletions.
110 changes: 110 additions & 0 deletions windows-terminal-quake/Native/TerminalProcess.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using Polly;
using Polly.Retry;
using Serilog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace WindowsTerminalQuake.Native
{
public static class TerminalProcess
{
private static readonly RetryPolicy Retry = Policy
.Handle<Exception>()
.WaitAndRetry(new[]
{
TimeSpan.FromMilliseconds(25),
TimeSpan.FromMilliseconds(50),
TimeSpan.FromMilliseconds(100),
TimeSpan.FromMilliseconds(250),
TimeSpan.FromMilliseconds(500)
},
onRetry: (ex, t) => Log.Error($"Error creating process: '{ex.Message}'"));

private static Process? _process;

private static List<Action> _onExit = new List<Action>();

private static bool _isExitting;

public static void OnExit(Action action)
{
_onExit.Add(action);
}

private static void FireOnExit()
{
_isExitting = true;

_onExit.ForEach(a => a());
}

public static Process Get()
{
return Retry.Execute(() =>
{
if (_isExitting) return _process!;

if (_process == null || _process.HasExited)
{
_process = GetOrCreate();
}

return _process;
});
}

private static Process GetOrCreate()
{
const string existingProcessName = "WindowsTerminal";
const string newProcessName = "wt.exe";

var process = Process.GetProcessesByName(existingProcessName).FirstOrDefault();
if (process == null)
{
process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = newProcessName,
WindowStyle = ProcessWindowStyle.Maximized
}
};

process.Start();
process.WaitForInputIdle();

// After starting the process, just throw an exception so the process search gets restarted.
// The "wt.exe" process does some stuff to ultimately fire up a "WindowsTerminal" process, so we can't actually use the Process instance we just created.
throw new Exception($"Started process");
}

// Try the "nice way" of waiting for the process to become ready
process.Refresh();
process.WaitForInputIdle();

Log.Information(
$"Got process with id '{process.Id}' and name '{process.ProcessName}' and title '{process.MainWindowTitle}'.");

// Make sure the process has not exited
if (process.HasExited) throw new Exception($"Process existing.");

// Make sure we can access the main window handle
// Note: Accessing mainWindowHandle already throws "Process has exited, so the requested information is not available."
if (process.MainWindowHandle == IntPtr.Zero) throw new Exception("Main window handle no accessible.");

// Make sure the process name equals "WindowsTerminal", otherwise WT might still be starting
if (process.ProcessName != "WindowsTerminal") throw new Exception("Process name is not 'WindowsTerminal' yet.");

// This is a way-too-specific check to further ensure the WT process is ready
if (process.MainWindowTitle == "DesktopWindowXamlSource")
throw new Exception($"Process still has temporary 'DesktopWindowXamlSource' window title.");

process.EnableRaisingEvents = true;
process.Exited += (s, a) => FireOnExit();

return process;
}
}
}
54 changes: 6 additions & 48 deletions windows-terminal-quake/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System;
using System.Diagnostics;
using Serilog;
using System;
using System.Linq;
using System.Windows.Forms;
using WindowsTerminalQuake.Native;
using WindowsTerminalQuake.UI;
using Serilog;

namespace WindowsTerminalQuake
{
Expand All @@ -21,18 +20,14 @@ public static void Main(string[] args)

try
{
var process = GetOrCreateWindowsTerminalProcess();
process.EnableRaisingEvents = true;
process.Exited += (sender, e) =>
{
Close();
};
_toggler = new Toggler(process);
TerminalProcess.OnExit(() => Close());

_toggler = new Toggler();

// Transparency
Settings.Get(s =>
{
TransparentWindow.SetTransparent(process, s.Opacity);
TransparentWindow.SetTransparent(TerminalProcess.Get(), s.Opacity);
});

var hks = string.Join(" or ", Settings.Instance.Hotkeys.Select(hk => $"{hk.Modifiers}+{hk.Key}"));
Expand All @@ -48,43 +43,6 @@ public static void Main(string[] args)
}
}

private static Process GetOrCreateWindowsTerminalProcess()
{
var process = Process.GetProcessesByName("WindowsTerminal").FirstOrDefault();

if (process == null)
{
process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "wt",
UseShellExecute = false,
RedirectStandardOutput = true,
WindowStyle = ProcessWindowStyle.Maximized
}
};
process.Start();

try
{
// Note: Accessing mainWindowHandle already throws "Process has exited, so the requested information is not available."
if (process.MainWindowHandle == IntPtr.Zero)
{
throw new Exception("Can not access newly started process.");
}
}
catch (Exception)
{
process = Process.GetProcessesByName("WindowsTerminal").First();
// _process.WaitForInputIdle();
process.Refresh();
}
}

return process;
}

private static void Close()
{
_toggler?.Dispose();
Expand Down
10 changes: 4 additions & 6 deletions windows-terminal-quake/Toggler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,20 @@ namespace WindowsTerminalQuake
{
public class Toggler : IDisposable
{
private Process _process;
private Process _process => TerminalProcess.Get();

private readonly List<int> _registeredHotKeys = new List<int>();

public Toggler(Process process)
public Toggler()
{
_process = process;

// Hide from taskbar
User32.SetWindowLong(_process.MainWindowHandle, User32.GWL_EX_STYLE, (User32.GetWindowLong(_process.MainWindowHandle, User32.GWL_EX_STYLE) | User32.WS_EX_TOOLWINDOW) & ~User32.WS_EX_APPWINDOW);

User32.Rect rect = default;
var ok = User32.GetWindowRect(_process.MainWindowHandle, ref rect);
var isOpen = rect.Top >= GetScreenWithCursor().Bounds.Y;
User32.ShowWindow(_process.MainWindowHandle, NCmdShow.MAXIMIZE);

var isOpen = true;

// Register hotkeys
Settings.Get(s =>
{
Expand Down

0 comments on commit ec978d7

Please sign in to comment.