Squirrel.windows: SquirrelAwareApp events not getting called

Created on 9 Sep 2015  路  12Comments  路  Source: Squirrel/Squirrel.Windows

I am having issues getting any of the SquirrelAwareApp events to execute. I have tried code very similar to the documentation and none of the shortcuts are getting created. I also have [assembly: AssemblyMetadata("SquirrelAwareVersion", "1")] in the last line of my AssemblyInfo.cs.

``` c#
using (var manager = new UpdateManager(SGGlobalState.UpdateUrl))
{
SquirrelAwareApp.HandleEvents(
onInitialInstall: _ => manager.CreateShortcutForThisExe(),
onAppUpdate: _ => manager.CreateShortcutForThisExe(),
onAppUninstall: _ => manager.RemoveShortcutForThisExe(),
onFirstRun: OnFirstRun);
}

I also tried creating my own event handlers however none of the methods are getting called.  I my wpf app, configuring squirrel is the second thing to happen, just after starting logging.

``` c#
public App()
{
    Logging.Start();
    ConfigureSquirrel();
}

private void ConfigureSquirrel()
{
    Logging.Log.Info("Creating SquirrelAwareApp event handlers...");
    SquirrelAwareApp.HandleEvents(
        onInitialInstall: OnInitialInstall,
        onAppUpdate: OnAppUpdate,
        onAppUninstall: OnAppUninstall,
        onFirstRun: OnFirstRun);
}

private static void OnFirstRun()
{
    Logging.Log.Info("Triggered OnFirstRun...");
}

private static void OnAppUninstall(Version version)
{
    Logging.Log.Info("Triggered OnAppUninstall...");

    using (var manager = new UpdateManager(SGGlobalState.UpdateUrl))
    {
        manager.RemoveShortcutsForExecutable("MyApp.exe", ShortcutLocation.Desktop);
        manager.RemoveShortcutsForExecutable("MyApp.exe", ShortcutLocation.StartMenu);
        manager.RemoveShortcutsForExecutable("MyApp.exe", ShortcutLocation.AppRoot);

        manager.RemoveUninstallerRegistryEntry();
    }
}

private static void OnAppUpdate(Version version)
{
    Logging.Log.Info("Triggered OnAppUpdate...");

    using (var manager = new UpdateManager(SGGlobalState.UpdateUrl))
    {
        manager.CreateShortcutsForExecutable("MyApp.exe", ShortcutLocation.Desktop, true);
        manager.CreateShortcutsForExecutable("MyApp.exe", ShortcutLocation.StartMenu, true);
        manager.CreateShortcutsForExecutable("MyApp.exe", ShortcutLocation.AppRoot, true);

        manager.RemoveUninstallerRegistryEntry();
        manager.CreateUninstallerRegistryEntry();
    }
}

private static void OnInitialInstall(Version version)
{
    Logging.Log.Info("Triggered OnInitialInstall...");

    using (var manager = new UpdateManager(SGGlobalState.UpdateUrl))
    {
        manager.CreateShortcutForThisExe();

        manager.CreateShortcutsForExecutable("MyApp.exe", ShortcutLocation.Desktop, false);
        manager.CreateShortcutsForExecutable("MyApp.exe", ShortcutLocation.StartMenu, false);
        manager.CreateShortcutsForExecutable("MyApp.exe", ShortcutLocation.AppRoot, false);

        manager.CreateUninstallerRegistryEntry();
    }
}

Most helpful comment

You don't need the UpdateApp call - you _do_ need to handle Squirrel events as _early as possible_ in your app though, which many folx mess up, they try to handle it in their update code. Like, you should be running HandleEvents in Main or in your WPF App.xaml.cs constructor. The earlier, the better!

All 12 comments

Same problem here with SquirrelAwareApps. I followed exactly as in the docs, but nothing happens.

In Squirrel log says that it detects that my exe is SquirrelAware, but when executed it times out after 15s, whether in install, uninstall or updated event, and nothing is executed.

I had similar problems. The app was detected as squirrel aware but the installer timeout after 15 sec. In my case the problem was caused by the .exe startup time(the executable needed more than 15 seconds to start because of a problem in our build process).

So to troubleshot this I would recommend:

  1. Double check the logs from squirrel. They are very useful when you trying for diagnostics. You can find then in %localAppData%\SquirrelTemp\SquirrelSetup.log and *%localAppData%\YourAppFolder*
  2. See if your executable which is marked as squirrel aware is called. You could do this by starting the installer and then check in process explorer if the process is started. You also could check the parameters of the process.

You could also try to start your .exe manually with "--squirrel-install" args. For example %localAppData%\app-\YouApp.exe --squirrel-install and see what is happening.

You could also try to start your .exe manually with "--squirrel-install" args. For example %localAppData%\app-\YouApp.exe --squirrel-install and see what is happening.

This is the easiest way to debug Squirrel hooks for sure - just run them!

I don't know if you have solved it by now, here are my 2垄:

I was also having problems getting the events, even after I noticed that I somehow forgot to add the SquirrelAwareVersion meta-data to my assembly.

Than I noticed that most events actually would come, e.g. the first run, just that my application wasn't updating.

After adding the UpdateApp code:

using (var updateManager = new UpdateManager(<url>) {
  await updateManager.UpdateApp();
}

and doing another setup, as the application didn't update, future updates finally started working.

Maybe I overlooked something, but in the article on Squirrel Events I couldn't find anything on still needing the UpdateApp() call. This threw me off, I thought that adding the assembly information and handling the events was all I needed.

It does make sense though, I am not complaining about the functionality, just that I also had difficulties making it work.

You don't need the UpdateApp call - you _do_ need to handle Squirrel events as _early as possible_ in your app though, which many folx mess up, they try to handle it in their update code. Like, you should be running HandleEvents in Main or in your WPF App.xaml.cs constructor. The earlier, the better!

The HandleEvents, in my test application, was called in the startup event of the Application (the Startup="MyStartupHandler" in App.xml).

The startup handler was async, might this have an influence that the update didn't work?
Events where handled, the uninstall and firstrun events were certainly working...

As I no longer am at work, I created a new WPF application and called the following in the constructor of App.xaml.cs:

using (var updateManager = new UpdateManager(ReleasesLocation))
{
    SquirrelAwareApp.HandleEvents(
        v => {
            updateManager.CreateShortcutForThisExe();
            MessageBox.Show("OnInitialInstall: " + v);
        },
        v => {
            updateManager.CreateShortcutForThisExe();
            MessageBox.Show("OnAppUpdate: " + v);
        },
        v => MessageBox.Show("OnAppObsoleted: " + v),
        v => {
            updateManager.RemoveShortcutForThisExe();
            MessageBox.Show("OnAppUninstall: " + v);
        },
        () => MessageBox.Show("OnFirstRun"));
}

The events are working fine as before, but updates still don't work.
So I was using 1.0.3 and made a releasify for 1.0.4, starting the 1.0.3 doesn't do anything else than show the application window. Everything will only work when calling UpdateApp myself, so I guess I must have done something wrong.

I know you wrote the thing :), but which part makes the update if an application is Squirrel-Aware?

P.S.
Just in case you are wondering:
Tested on Windows 7 at work, and at home I used Windows 10.

Hi Paul,

I had a quick look at https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/SquirrelAwareApp.cs, at least in HandleEvents there is no update being called (which doesn't surprise me).

Is the update for Squirrel-Aware applications done in the update.exe?
I would say "no" as in my shortcut it says "Update.exe --processStart TestExe.exe", and I believe that the update.exe doesn't know the "releases" url. So I somehow don't understand what would be doing the updating if I don't do it myself?

As I said before, the event handling in general works fine. Except that there is no update even, or rather no update at all, when I don't call the update code myself. And this too is fine, just that it is not clearly documented.

Best wishes,
Robin

As I said before, the event handling in general works fine. Except that there is no update even, or rather no update at all, when I don't call the update code myself.

I think you're misunderstanding how this works - HandleEvents is a mechanism for _Squirrel_ to tell you when things happen. Squirrel never automatically updates, because it's the developer's job to decide when updates happen. Sorry if that wasn't clear in the docs! Squirrel is much more a library, than an automated "framework" like Clickonce et al

Thanks Paul, your answer "You don't need the UpdateApp call" just threw me off.

So I guess the squirrel-events documentation here should be enhanced with a hint that an update check and the update itself needs to be added.

For me, placing the following as soon as possible in the application worked:

    static bool ShowTheWelcomeWizard;

    using (var mgr = new UpdateManager(updateUrl))
    {
        // Note, in most of these scenarios, the app exits after this method completes!
        SquirrelAwareApp.HandleEvents(
          onInitialInstall: v => mgr.CreateShortcutForThisExe(),
          onAppUpdate: v => mgr.CreateShortcutForThisExe(),
          onAppUninstall: v => mgr.RemoveShortcutForThisExe(),
          onFirstRun: () => ShowTheWelcomeWizard = true);

          await mgr.UpdateApp();
    }

The above code works for me for updating but the initial instance does not close after update so 2 versions of my app end up being open.

Running Squirrel 1.5.2 I'm having trouble getting anything but the onFirstRun event to fire. The main issue right now is the onUninstall event, as this is causing the desktop shortcut to be left behind and the Splash screen is displayed when the app is uninstalled.

AssemblyInfo.cs - line appended:
[assembly: AssemblyMetadata("SquirrelAwareVersion", "1")]

Main.cs excerpt:

private static void myOnFirstRun() {
  try {
    using (var mgr = new Squirrel.UpdateManager("\\\\UNC\\Squirrel", "AppName")) {
    log.Debug("Creating shortcuts...");
    mgr.CreateShortcutsForExecutable(Path.GetFileName(System.Windows.Forms.Application.ExecutablePath), Squirrel.ShortcutLocation.Desktop, false);

    log.Debug("Creating uninstaller...");
    mgr.CreateUninstallerRegistryEntry().Wait();
    log.Debug("... done creating uninstaller.");
  } catch (System.Exception ex) {
    log.Error("myOnFirstRun. "+ ex.Message);
  }
}

private static void onAppUpdate(Version version) {
  try {
    using (var mgr = new Squirrel.UpdateManager("\\\\UNC\\Squirrel", "AppName")) {
      MessageBox.Show("Thanks for updating!");
      log.Debug("Rereating shortcuts...");
      mgr.CreateShortcutsForExecutable(Path.GetFileName(System.Windows.Forms.Application.ExecutablePath), Squirrel.ShortcutLocation.Desktop, false);
    }

  } catch (System.Exception ex) {
    log.Error("onAppUpdate. "+ ex.Message);
  }
}

private static void myOnAppUninstall(Version version) {
  try {
    System.Diagnostics.Process.Start("https://www.google.com");

    using (var mgr = new Squirrel.UpdateManager("\\\\UNC\\Squirrel", "AppName")) {
        log.Debug("Removing shortcuts...");
        mgr.RemoveShortcutsForExecutable(Path.GetFileName(System.Windows.Forms.Application.ExecutablePath), Squirrel.ShortcutLocation.Desktop);
    }
  } catch (System.Exception ex) {
    log.Error("myOnAppUninstall. "+ ex.Message);
  }
}

private static void myOnInitialInstall(Version version) {
  try {
    log.Debug("Welcome! v" + version.ToString());
  } catch (System.Exception ex) {
    log.Error("myOnInitialInstall. "+ ex.Message);
  }
}


[STAThread]
private static void Main(string[] args) {
    //Set up logging
    initialiseFiles();

    try {
      log.Debug("Setting up Squirrel handlers.");
      Squirrel.SquirrelAwareApp.HandleEvents(
            onFirstRun: myOnFirstRun,
            onInitialInstall: v => myOnInitialInstall(v),
            //onAppUpdate: v => onAppUpdate(v),
            onAppUninstall: myOnAppUninstall
       );

    } catch (System.Exception ex) {
        log.Error("Failed setting up handlers.");
        OGCSexception.Analyse(ex, true);
    }

    Splash.ShowMe();

Can anyone point out what I'm doing wrong? Passing the version variable into the function or not doesn't appear to make any difference.

OK, I worked it down to a problem with HandleEvents() - if the application is pre-release, eg 2.5.0-beta, then it fails. Given this is a valid SemVer, I'm feeling like this is a bug.

I've subsequently come across issue #892 and a comment that also need to strip the pre-release detail.

For the moment, my workaround is:

Squirrel.SquirrelAwareApp.HandleEvents(
  onFirstRun: myOnFirstRun,
  onInitialInstall: v => myOnInitialInstall(v),
  onAppUpdate: v => onAppUpdate(v),
  onAppUninstall: v => myOnAppUninstall(v),
  arguments: FixCliArgs()
);

private static String[] FixCliArgs() {
  try {
    String[] cliArgs = Environment.GetCommandLineArgs().Skip(1).ToArray();
    if (cliArgs.Length == 2) {
      cliArgs[1] = cliArgs[1].Split('-')[0];
    }
    return cliArgs;
  } catch (System.Exception ex) {
    return null;
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mihaimyh picture mihaimyh  路  4Comments

joshiji picture joshiji  路  6Comments

Andrew-Hanlon picture Andrew-Hanlon  路  6Comments

Andrew-Hanlon picture Andrew-Hanlon  路  4Comments

greyivy picture greyivy  路  4Comments