Windows - Electron using protocol (with parameters) to 'do something' in the current active electron app

Viewed 1767

UPDATED BELOW

Note: This app is for windows only so it rules out 'open-url' etc.

I have the protocol working for my application and it opens the electron app successfully however what I am looking for is so that if the app is open and the user clicks on a protocol link with parameters ( my-app://go/to/this/section ) it will open the current application and run a function to go to the link.

What actually is happening at the minute is the application opens another version of itself and not passing the arguments.

I've got the setAsDefaultProtocolClient function in my app.js to try and catch any instances of the protocol but this doesn't seem to be working.

const {remote} = window.require('electron');    
remote.app.setAsDefaultProtocolClient( 'my-app' );

I also have the makeSingleInstance function in my main process to only allow one instance of the app to run at one time however it doesn't seem to be sending the args I pass with the protocol when closing the second client.

// Make sure there is only 1 instance of the app running at a time
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
    if (mainWindow) {
        if (mainWindow.isMinimized()) mainWindow.restore();
        mainWindow.focus();
    }
});
// If this is a second instance of the app close it
if (isSecondInstance) {
    app.quit();
}

UPDATE:

I've now got the second window posting its protocol to the original instance of the application however I can't log the arguments.

Whenever I log process.argv and use 'my-app://section/29 it is just the directory to the install directory and doesn't have any parameters.

I've added the following to the makeSingleInstance

if (process.platform == 'win32') {
    deeplinkingUrl = process;
    // Keep only command line / deep linked arguments
    logEverywhere( process );
}

Here is logEverywhere just for reference:

function logEverywhere(s) {
    console.log(s);
    if (mainWindow && mainWindow.webContents) {
        mainWindow.webContents.executeJavaScript(`console.log("${s}")`);
    }
}
2 Answers

New versions of Electron have changed how this works. makeSingleInstance is deprecated. use requestSingleInstanceLock instead. This is a sample.

import { app, ipcMain as ipc } from 'electron'
import { find, compact } from 'lodash'
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    // mainWindow is window created with `new BrowserWindow(params)`
    if (mainWindow) {
      // And use ipc, or promiseIpc to send the command line 
      // to the renderer to handle it however we want
      const cmd = find(commandLine, cmd => {
        return cmd.indexOf('app-protocol-name') > -1
      })
      let actualCommands = cmd.replace('app-protocol-name://', '')
      actualCommands = compact(actualCommands.split('/'))
      ipc.send('NEW_COMMAND_LINE', mainWindow, actualCommands)
      mainWindow.show()
      mainWindow.restore()
      mainWindow.focus()
    }
  })
}

commandLine will be an array of 10 elements or more sometimes. So you have to search it for the element that actually contains the protocol. Then split and handle the parameters appropriately. This code will not handle things like forward slashes, or quotes, etc. But it's a start

Related