Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Squirrel to NSIS migration #837

Closed
dustintownsend opened this issue Oct 19, 2016 · 36 comments
Closed

Squirrel to NSIS migration #837

dustintownsend opened this issue Oct 19, 2016 · 36 comments

Comments

@dustintownsend
Copy link

I see that the previous Squirrel default is being moved to NSIS, so I was curious if there would be a path for people to migrate from Squirrel to NSIS?

For example, I do a new release to my current Squirrel set-up that would migrate the existing installation to NSIS. This would be so the end user wouldn't have to do an uninstall and reinstall.

I haven't dug into NSIS enough to know if something like this would be possible.

@develar
Copy link
Member

develar commented Oct 19, 2016

if something like this would be possible.

Definitely it is possible and will be implemented in this way.

When NSIS will be set as default target — migration tutorial will be provided and some option to auto uninstall old Squirrel.Windows installation will be implemented.

Please do not worry — deprecation doesn't mean that we will not support Squirrel.Windows, you can continue to use Squirrel.Windows if it is suitable for your app. But do not expect enhancements.

@dustintownsend
Copy link
Author

dustintownsend commented Oct 19, 2016

@develar that is not the answer I was expecting, but I am glad to hear it!

My situation is I'm rewriting a legacy .NET app with Electron. I moved the .NET app to Squirrel last year to take advantage of the auto updates. My plan was to build the Electron app installer using Squirrel to upgrade users on the .NET app to the new Electron app. Then, I saw that you are going away from Squirrel so I was worried.

I'll continue on with my original plan, but I do want to migrate to NSIS due to the benefits I saw you outlined in other discussions. Mainly the reduction in installer size is what I would like.

@develar
Copy link
Member

develar commented Oct 20, 2016

that is not the answer I was expecting

And what did you expect ;)?

@dustintownsend
Copy link
Author

dustintownsend commented Oct 20, 2016

And what did you expect ;)?

Well not knowing anything about NSIS and just enough about Squirrel to be dangerous... I assumed it would be a difficult task and may not be worth the effort to do. I'm glad my assumptions were wrong.

@jessb321
Copy link

jessb321 commented Oct 22, 2016

@dustintownsend for me at least - migrating to NSIS was fairly simple if you are already using the default electron api for auto-updating. You effectively just have to change the module, and then remove the feedurl bits since its done from bintray (at the moment anyway!)
Edit: I should clarify that I was not using the default electron api for my application before i move to NSIS - I was using this for my updating as hosting my own server was not quite viable.

@TimvdEijnden
Copy link
Contributor

@develar

Is there a tutorial available to migrate from Squirrel.Windows to NSIS? We would like our users to update and switch to NSIS automatically. How can we do this? We're also using https://github.com/Aluxian/squirrel-updates-server to fetch our updates from GitHub i guess we also need to change that.

Squirrel is reporting a lot of Errors and since the version is not updated anymore in Electron-builder we cannot update easily. Or is an update to the latest Squirrel.Windows easy to do?

We're open to switching to NSIS if we don't have to change a lot and more important our users won't notice it, meaning they don't have to uninstall and install a new version.

@develar
Copy link
Member

develar commented Dec 14, 2016

is an update to the latest Squirrel.Windows easy to do?

@TimvdEijnden Squirrel.Windows updated to 1.5.1 As always, release will be available in 20 minutes. You are not forced to use NSIS if Squirrel.WIndows is suitable for you.

Is there a tutorial available to migrate from Squirrel.Windows to NSIS

Not yet.

@p4tb0l
Copy link

p4tb0l commented Jan 23, 2017

Hello and thank you for your work.
We are also looking forward to this development.
Here is our scenario: we already have users on a Squirrel version, and some users can not install the application because they have neither admin rights nor .net framework (which is a dependency of Squirrel).
An automatic update from Squirrel to NSIS would prevent us from having to maintain 2 parallel versions.

Do you have a schedule to make this evolution available?

@develar
Copy link
Member

develar commented Jan 23, 2017

Schedule depends on user demands. I will try to find time to implement migration (actually, I think, maybe it works even now, need to to test and tweak some settings).

@develar
Copy link
Member

develar commented Feb 14, 2017

Sorry for delay :) I hope it will be addressed tomorrow morning CET.

@develar develar added feature and removed question labels Feb 14, 2017
@sklink
Copy link

sklink commented Feb 23, 2017

How are things coming along with this? Anything I can do to help?

@p4tb0l
Copy link

p4tb0l commented Apr 5, 2017

Hello,
Sorry to insist, but I really need to migrate from squirrel to NSIS.
Could you explain to me the principle you plan to implement? What can we do to help?

@ghost
Copy link

ghost commented Apr 5, 2017

@p4tb0l, you can try to do it by yourself. The simple idea is to download NSIS installer manually (not as auto-update) and launch it by child process. Main process should follow uninstall flow.

@p4tb0l
Copy link

p4tb0l commented Apr 10, 2017

When the nsis install package is launched, it prompts the user to close the existing app but doesn't uninstall it.
Do I have to uninstall it manually or is there something that I'm missing?

@develar
Copy link
Member

develar commented Apr 10, 2017

Do I have to uninstall it manually or is there something that I'm missing?

NSIS for now can automatically uninstall only NSIS apps.

@ghost
Copy link

ghost commented Apr 14, 2017

Do I have to uninstall it manually or is there something that I'm missing?

Yes manually, but you can control your current launched app ;)

@esamelson
Copy link

esamelson commented May 4, 2017

I'm trying to do something similar but with another complication - some of our users have used the Squirrel "Machine-Wide" installer and have the app installed on multiple user accounts. I'd like to remove all of these installations in favor of a single NSIS-based one in C:\Program Files.

I've written a custom NSIS script to loop through every user account and attempt to run Squirrel's own uninstaller. This removes the app from each account's AppData\Local folder, but it does not remove the registry entry or shortcuts for any account besides the current one. (I can't use runas since that prompts for a password.) Do I just need to add those steps into my script as well? Or is there a simpler way to do this?

@develar
Copy link
Member

develar commented May 5, 2017

@esamelson you can simply call Squirrel Setup.exe (wrapper) as uninstaller passing some args (sorry, cannot provide details yet).

@esamelson
Copy link

Do you mean Squirrel's Update.exe? If so, that's what I've been doing - calling %LOCALAPPDATA%\MyApp\Update.exe --uninstall in each user's folder. The problem is Update.exe doesn't remove the registry entry or shortcuts for any user besides the one I'm signed into.

I also tried running MyAppSetup.exe --uninstall but that gave me an error. Is there a different Squirrel Setup.exe I'm missing??

@eanders-ms
Copy link

@esamelson May I ask how you're calling Squirrel Update.exe --uninstall? I also need to uninstall the old Squirrel-based app, and wondering where to put this call. Thanks!

@esamelson
Copy link

I'm running that in an NSIS include script, as a macro (see https://github.com/electron-userland/electron-builder/wiki/NSIS). Here's a gist link to my code, in case you want to take a look. I've chosen to run it in customInit but it could easily be run in customInstall as well, I believe. It's a little bit hacky, especially the way it cycles through all of the users, but it has worked for me so far.

https://gist.github.com/esamelson/a6af4c7ad53ba52d96c4cffd36cc3981

An important note - this will NOT remove the registry entries for any user other than the one running the script. It will remove only the app and shortcuts.

@eanders-ms
Copy link

Thanks esamelson, very helpful. That's an interesting ASM-like macro language. Thankfully I only need to do it for the current user!

@black-snow
Copy link
Contributor

Is there anything left open here?

@PierBover
Copy link

Any guide or tutorial on how to migrate from Squirrel to NSIS?

I just saw that NSIS has become the default win target, but I have no idea what the implications are.

Will NSIS still work with electron-release-server?

If compiling to both macOS and Windows, does my Node code need to account for each platform differently?

Quite frankly switching to NSIS by default seems like a very drastic move considering the Electron project still recommends Squirrel for Windows.

@AshDevFr
Copy link

Is there a way to run DeleteRegKey HKCR ... commands with this custom script during the install.
I'd like to remove old protocol handler from the squirrel app.

@develar
Copy link
Member

develar commented Sep 12, 2017

@AshDevFr
Copy link

@develar I tried to run some DeleteRegKey commands in customInstall but they don't remove the keys from the registry.
I tried with and without perMachine: true

@develar
Copy link
Member

develar commented Sep 12, 2017

@omichelsen
Copy link

omichelsen commented Jan 6, 2018

I just moved from Squirrel.Windows to NSIS and needed to uninstall old the Squirrel installation as well. Digging through the good suggestions in this thread I came up with this basic solution:

Add a build/installer.nsh file with the following content:

!macro customInit
  nsExec::Exec '"$LOCALAPPDATA\MYAPPNAME\Update.exe" --uninstall -s'
!macroend

Remember to substitute "MYAPPNAME" for your own.

This will uninstall the Squirrel version for the current user when you install the new NSIS version.

Just a little input to whomever will take it upon themselves to write a transition guide at some point.

@develar
Copy link
Member

develar commented Jan 31, 2018

Help-wanted if someone want to adds docs. Comments above is useful to migrate.

@konstantinkreft
Copy link

konstantinkreft commented Jan 10, 2019

Thanks @omichelsen for your macro.

This did work for me on the initial installation of the new nsis electron app. But afterward, I could not update the app. I could narrow it down to the problem that the old squirrel $LOCALAPPDATA\MYAPPNAME\Update.exe is still present after successfully uninstalling the old app. There is an open issue regarding that in the Squirrel.Windows repo: Squirrel/Squirrel.Windows#221

The solution for me is to remove the leftover files. I modified @omichelsen installer.nsh and made sure that it is only executed on installation and not on updates:

!macro customInit
  ${ifNot} ${isUpdated}
    nsExec::Exec '"$LOCALAPPDATA\MYAPPNAME\Update.exe" --uninstall -s'
    delete "$LOCALAPPDATA\MYAPPNAME\Update.exe"
    delete "$LOCALAPPDATA\MYAPPNAME\.dead"
    rmDir "$LOCALAPPDATA\MYAPPNAME"
  ${endIf}
!macroend

Remember to substitute "MYAPPNAME" for your own.

@adam-lynch
Copy link
Contributor

I've just noticed this file is left behind in Roaming as well (Windows 10):

$APPDATA\Microsoft\Windows\Start Menu\Programs\AUTHORNAME\PRODUCTNAME.lnk

PRODUCTNAME is the user friendly name of your app, like Hello World instead of hello-world. It's called title in the nupkg manifest.

AUTHORNAME matches the author name I put in the author field in my package.json.

@xmedeko
Copy link

xmedeko commented Apr 14, 2020

A possible solution to make auto update Squirell.Windows to NSIS could be (not tested):

  1. Let say you have myapp.exe, make a NSIS installer and rename it to myapp.exe.
  2. Make a nupkg full for Squirell.Windows containing just the myapp.exe and release it.

The Electron auto updater will install the myapp.exe - the NSIS installer - and run it. Then the proper myapp is installed.

@adam-lynch
Copy link
Contributor

adam-lynch commented Apr 14, 2020

I've been working on that. I extract the nupkg electron-builder makes, replace the executable, archive/pack it again, and update the filesize hardcoded in the RELEASES file (otherwise an error is thrown when updating).

One issue I found is the NSIS installer is opened multiple times by Squirrel and electron-builder uses NSIS scripts to only allow one instance of the installer. I've commented out some of that stuff but I'm still getting errors. I'll reply here again if I get this to work.

Edit: I might also need to update a checksum in RELEASES but I'm not sure. The errors I'm getting right now are related to the NSIS scripts I think

@adam-lynch
Copy link
Contributor

adam-lynch commented Apr 15, 2020

I couldn't quite get that to work because the installer is being ran inside the directory that the Squirrel uninstall step tries to delete. I couldn't figure out how to get NSIS to run the (Squirrel) uninstall at the end of a successful install, like a post-install hook. That might have been a workaround.

Anyway, this is my solution:

  1. I build for NSIS and Squirrel using electron-builder. I'll explain later what the NSIS installer does.
  2. Extract the nupkg archive which was created.
  3. Copy the NSIS installer over the app executable.
  4. Pack the nupkg again and replace the old one. See this for how electron-builder does it:
    const archive = archiver("zip", {zlib: {level: Math.max(1, (options.packageCompressionLevel == null ? 9 : options.packageCompressionLevel))}})
  5. Update the RELEASES file which was generated. This means updating the checksum (which from looking at the Squirrel.Windows source I think is a SHA1 hash of the nupkg) and the file size (of the nupkg).
  6. Make the app check for updates using that RELEASES file / server if it already isn't (i.e. set the correct feed URL).
  7. Once a user's app checks for an updates, it downloads the nupkg and does it's normal steps, including running what should be the app but is actually the NSIS installer.
  8. The NSIS installer contains some custom initialization steps if the app is being installed (not updated);
    1. It creates an empty file in the app directory in AppData\Local as a marker that it should be uninstalled. This will be done once the app runs.
    2. It deletes the start menu shortcut which the Squirrel uninstall step misses (Squirrel to NSIS migration #837 (comment)). This could be done when the app runs but it's probably best to do it at this point in case it conflicts with your new installer 🤷.
    3. It deletes the parent directory of the shortcut if it's not empty (there may be other apps by the same author).
  9. The NSIS installer installs the app to AppData\Local\Programs and runs it.
  10. When the app starts, it checks for the uninstall marker in the Squirrel app directory and if it's there it:
    1. Runs the Squirrel uninstall step (Update.exe --uninstall -s). I use execa.
    2. Deletes the app directory in AppData\Local completely (i.e. no .dead etc. is left behind). I use del with { force: true }.

NSIS custom initialization steps

This is my buildResources/installer.nsh:

!macro customInit
  ${ifNot} ${isUpdated}
    ; Create uninstall marker if Squirrel app exists
    ${if} ${FileExists} "$LOCALAPPDATA\${APP_PACKAGE_NAME}"
      FileOpen $9 "$LOCALAPPDATA\${APP_PACKAGE_NAME}\.shouldUninstall" w
      FileClose $9
    ${endIf}

    ; Delete the start menu shortcut
    Delete "$APPDATA\Microsoft\Windows\Start Menu\Programs\${COMPANY_NAME}\${PRODUCT_NAME}.lnk"
    ; Delete the parent directory if it's not empty (because there's no /r)
    RMDir "$APPDATA\Microsoft\Windows\Start Menu\Programs\${COMPANY_NAME}"
  ${endIf}
!macroend

I explained what it does above. I just want to point out that those variables work for me, but they might not for you. E.g. for me, APP_PACKAGE_NAME is hello-world, PRODUCT_NAME is Hello World, and COMPANY_NAME is Adam Lynch. There isn't really any electron-builder documentation on these. If I were you, look through the electron-builder source for these and other defined variables (there are a handful more which are very similar). See how they're populated and used. Find what works for you.

Keep in mind that the files installed on an existing user's disk were installed by something else (a Squirrel installer, which may have been created by something else or even if it was electron-builder, it could've been an older version of it).

Or if you're sure, you could hardcode the paths yourself.

Other notes

  • While working on this I had to manually edit the NSIS scripts created by electron-builder (well app-builder-lib) because the auto-update was failing because the installer didn't like multiple instances of itself running (Squirrel to NSIS migration #837 (comment)), but now in the end, that doesn't seem to be needed anymore. I'm not sure why but it seems to work fine.
  • The uninstall marker isn't strictly necessary but I wanted to be safe and not just run the uninstaller if an Update.exe exists at the location. To make it even more certain, the last Squirrel release could create the uninstall marker before it checks for updates.
  • There are probably ways to avoid the disk lookup for the uninstall marker each time the app is launched, but I'll leave that up to you. Keep in mind those that the installer might be ran multiple times during the auto-update transition.
  • The NSIS-installed app can use electron-updater. There won't be an issue.
  • The installer could be copied over the Update.exe in the nupkg but I don't think that'll make much of a difference. I haven't tried it though.

@adam-lynch
Copy link
Contributor

Quick follow-up... it is possible to only have the new installer in /lib/net45 in the nupkg (along side /lib's siblings). It saves me 39% in filesize. (Only having an Update.exe in /lib/net45, that is in fact the installer, doesn't work)

This also means you could get away without setting electron-builder to build for the squirrel target and create this dummy nupkg yourself. You'd have to copy some code from electron-builder (the template for the _rels/.rels, etc.), you'd need to write the RELEASES file from scratch (not difficult), and you might miss future related fixes in electron-builder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests