Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
Further improvements to new HandlEvents function
Browse files Browse the repository at this point in the history
  • Loading branch information
caesay committed Jan 15, 2022
1 parent ad72617 commit cb61eda
Showing 1 changed file with 39 additions and 32 deletions.
71 changes: 39 additions & 32 deletions src/Squirrel/SquirrelAwareApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ namespace Squirrel
/// <param name="tools">Helper functions for managing application shortcuts and registry</param>
public delegate void SquirrelHook(SemanticVersion version, IAppTools tools);

/// <summary>
/// A delegate type for handling Squirrel command line events easily
/// </summary>
/// <param name="version">The currently executing version of this application</param>
/// <param name="tools">Helper functions for managing application shortcuts and registry</param>
/// <param name="firstRun">True if this is the first run following application installation</param>
public delegate void SquirrelRunHook(SemanticVersion version, IAppTools tools, bool firstRun);

/// <summary>
/// SquirrelAwareApp helps you to handle Squirrel app activation events
/// correctly.
Expand All @@ -21,10 +29,10 @@ namespace Squirrel
public static class SquirrelAwareApp
{
/// <summary>
/// This function is obsolete and will be removed in a future version.
/// See <see cref="HandleEvents(SquirrelHook, SquirrelHook, SquirrelHook, SquirrelHook, Action, string[])" />
/// This overload is obsolete and will be removed in a future version.
/// See <see cref="HandleEvents(SquirrelHook, SquirrelHook, SquirrelHook, SquirrelHook, SquirrelRunHook, string[])" />
/// </summary>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
//[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
[Obsolete("Use the HandleEvents overload which provides a SemanticVersion as the argument")]
public static void HandleEvents(
Action<Version> onInitialInstall = null,
Expand Down Expand Up @@ -82,56 +90,55 @@ public static void HandleEvents(
/// <param name="onAppUninstall">Called when your app is uninstalled
/// via Programs and Features. Remove all of the things that you created
/// in onInitialInstall.</param>
/// <param name="onFirstRun">Called the first time an app is run after
/// being installed. Your application will **not** exit after this is
/// dispatched, you should use this as a hint (i.e. show a 'Welcome'
/// screen, etc etc.</param>
/// <param name="onEveryRun">Called when your application is run normally,
/// also indicates whether this is first time your app is run, so you can
/// show a welcome screen. Also see <see cref="IAppTools.SetProcessAppUserModelId"/>
/// which can be executed here.</param>
/// <param name="arguments">Use in a unit-test runner to mock the
/// arguments. In your app, leave this as null.</param>
public static void HandleEvents(
SquirrelHook onInitialInstall = null,
SquirrelHook onAppUpdate = null,
SquirrelHook onAppObsoleted = null,
SquirrelHook onAppUninstall = null,
Action onFirstRun = null,
SquirrelRunHook onEveryRun = null,
string[] arguments = null)
{
SquirrelHook defaultBlock = ((v, t) => { });
var args = arguments ?? Environment.GetCommandLineArgs().Skip(1).ToArray();
if (args.Length == 0) return;

var lookup = new[] {
var fastExitlookup = new[] {
new { Key = "--squirrel-install", Value = onInitialInstall ?? defaultBlock },
new { Key = "--squirrel-updated", Value = onAppUpdate ?? defaultBlock },
new { Key = "--squirrel-obsolete", Value = onAppObsoleted ?? defaultBlock },
new { Key = "--squirrel-uninstall", Value = onAppUninstall ?? defaultBlock },
}.ToDictionary(k => k.Key, v => v.Value);

if (args[0] == "--squirrel-firstrun") {
(onFirstRun ?? (() => { }))();
return;
}

if (args.Length != 2) return;

if (!lookup.ContainsKey(args[0])) return;
var version = new SemanticVersion(args[1]);

try {
// CS: call dispose immediately means this instance of UpdateManager
// can never acquire an update lock (it will throw if tried).
// this is fine because we are downcasting to IAppTools and no
// functions which acquire a lock are exposed to the consumer.
var um = new UpdateManager(null, null);
um.Dispose();

lookup[args[0]](version, um);
// CS: call dispose immediately means this instance of UpdateManager
// can never acquire an update lock (it will throw if tried).
// this is fine because we are downcasting to IAppTools and no
// functions which acquire a lock are exposed to the consumer.
// also this means the "urlOrPath" param will never be used,
// so we can pass null safely.
var um = new UpdateManager(null);
um.Dispose();

if (!ModeDetector.InUnitTestRunner()) Environment.Exit(0);
} catch (Exception ex) {
LogHost.Default.ErrorException("Failed to handle Squirrel events", ex);
if (!ModeDetector.InUnitTestRunner()) Environment.Exit(-1);
// in the fastExitLookup arguments, we run the squirrel hook and then exit the process
if (fastExitlookup.ContainsKey(args[0]) && args.Length >= 2) {
var version = new SemanticVersion(args[1]);
try {
fastExitlookup[args[0]](version, um);
if (!ModeDetector.InUnitTestRunner()) Environment.Exit(0);
} catch (Exception ex) {
LogHost.Default.ErrorException("Failed to handle Squirrel events", ex);
if (!ModeDetector.InUnitTestRunner()) Environment.Exit(-1);
}
}

// otherwise we execute the 'everyrun' hook with the firstRun parameter.
bool firstRun = args[0] == "--squirrel-firstrun";
onEveryRun?.Invoke(um.CurrentlyInstalledVersion(), um, firstRun);
}
}
}

0 comments on commit cb61eda

Please sign in to comment.