Last time we created a dmg installer for macOS. Now it’s time to look at an Electron Windows installer with Electron-winstaller. This tutorial expects you to build the installer on Windows.
Running this with the following command would create an installer for us in release-builds/windows-installer.
If you get an error complaining about to long path names, have a look at the asar tutorial.
Handling squirrel install events
Now the readme of electron-winstaller tells us to handle squirrel events inside our app. This will help us with the installation and also create shortcuts for us. The script below is copied directly from that readme. I’ve just wrapped it in module.exports so that we can require it from main.js
Start by creating a file called setupEvents.js in the folder installers/
And in main js we’ll require this file at the beginning:
Adding script shortcuts
As we have done with the packager and dmg installer scripts we will add a script shortcut to the Windows installer script in package.json:
Now you can run the following to create a Windows installer:
Signing installer
The readme of electron-winstaller tells you to sign your installer. Read more about why.
To create a DMG installer for our Electron app we can use the electron-installer-dmg package.
In this tutorial we’ll create a DMG installer for the Electron tutorial app. To create a DMG installer you first need to package the app. Read that tutorial first if you haven’t already.
1. Installing package
Open up a terminal and run these commands:
2. Creating the DMG installer
This is the basics that we need to create the DMG. First run the package-mac script that we created to create a package for the mac in the electron packager tutorial:
This will create a package for us in the release-builds folder. So now we can create the DMG with this command:
This will create a file called electron-tutorial-app.dmg in the root folder of the application. The dmg will use default settings. In the next step we’ll look at what settings we can do to it.
3. Usage
If we look at the file usage.txt we can see that we have some options to make when it comes to the installer:
As you see above we can set the out path of the .dmg file that is generated. We can set an icon that the dmg-window will use (By default this was the electron icon when i tried). We can set the icon size and custom background for the window.
Since the packages are created in the release-builds folder we’ll create the installers there as well. We also already have the icon created for the application (this is done in the icon tutorial)
The command to run now looks like this:
4. Creating a script
I am one of those that won’t be able to memorize that string. So we can add it to our scripts package.json:
Packaging your app into an asar archive speeds up requires a bit, it conceals the source code and helps to avoid long path names on Windows. Asar is an archive format that concatenates files together without compression.
I got this error when building a Windows installer for an electron app with electron winstaller:
"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."
This was because of a package in node_modules that created very long paths.This did however work on Linux and MacOS. The solution was to package my app with asar before creating the installer.
Asar and electron packager
Install the asar package globally:
In the Electron tutorial app we use electron packager. To the build script we can pass –asar=true in package.json:
So now when we do a npm run package-mac our app will have a file called app.asar in it instead.
You can also do this without electron packager with this command:
Lets look at IPCMain and IPCRenderer in Electron. We can use it to send messages between main and renderer processes.
Over at the forums there was a developer who needed to open a second app window from the main process when the user had done something in the renderer process. So I thought we could look at a real world example. So in this tutorial we’ll wait for the user to click a button. Then we’ll send a message to the main process which in turn opens a new window.
1. Setting up a new window in main.js
Fire up the Electron tutorial app or your own app, and open main.js. The additions are highlighted in bold.
We create a new variable to hold our second window with let secondWindow and by now you know how to create a new BrowserWindow. But this time the size of the window has changed. And we also don’t show a frame, so we set that to frame:false. This is because we close the window from a button that we create ourselves instead of using the standard os-buttons. If the user closes the new window with the built in close button they wont be able to open it again because it’s not initialized anymore.
We also set mainWindow as parent so that secondWindow will stay on top of the parent window. There are some platform specific handling to the parent setting:
On macOS the child windows will keep the relative position to parent window when parent window moves, while on Windows and Linux child windows will not move.
On Windows it is not supported to change parent window dynamically.
On Linux the type of modal windows will be changed to dialog.
On Linux many desktop environments do not support hiding a modal window
The secondWindow also loads another .html file called ipcwindow.html that is located in a folder called windows. Lets look at that next.
2. IPCWindow content
Create a new folder called windows. In that folder you create ipcwindow.html. Add this content to the html file:
3. Changes in navigation menu and who we are section
When this tutorial is being written the navigation menu and who we are section looks like this:
Navigation menu - who we are
Change the name of the menu-item to IPC/Remote in the en.js and sv.js translations
Also rename sections/whoweare.html to ipcremote.html. Then update link=rel and the sidebar menu in index.html:
In ipcremote.html we also need to update the id of the section to ipcremote and adding some information about what will happen if we click the button:
4. IPCRenderer
Now we’ve got our app set up and it’s finally time to move on to sending and receiving messages with IPC. This will be done asynchronous.
Create a file called ipc.js in assets/js/. To start with you can add this content to it:
init() is called on documentready. That in turn hooks up an onclick event on the button in the ipc section with id #open-secondwindow-button. Now to the ipc stuff. When that button is clicked ipcRenderer.send is invoked like this: ipcRenderer.send(‘open-second-window’, ‘an-argument’) The first value sent as a parameter is the name of the event. The second one is an argument of your own choice.
and add a require statement to the file in index.html:
5. IPCMain
Now it is time to listen for this event in main.js. Start by adding a require statement for ipcMain at the top of the file:
And to listen to the event and showing the second window just add this code:
And at this point the tutorial on ipc main and renderer is over. But we’ll do it once more just to be able to close the secondwindow again.
6. Closing a BrowserWindow
Open up ipc.js again and add another on click event that sends a closing message to main:
And in main we add another event listener:
Ipc also needs to be required from ipcwindow.html:
That’s it for this tutorial. Check out the official documentation on IPCMain and IPCRenderer