electron / electron

:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS

Home Page:https://electronjs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

process.argv differs in built electron apps

brian-mann opened this issue · comments

  • Electron version: 0.36.9
  • Operating system: OSX

I have an application that can accept CLI arguments. I noticed when I built the app that process.argv is not the same as when running electron while developing.

When running electron from the command line process.argv looks like:

electron ./my-app --foo --ping=123
[
  '/Users/bmann/Dev/my-app/node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron',
  './my-app',
  '--foo',
  '--ping=123'
]

This is good because typically when you parse CLI args you do something like:
minimist(process.argv.slice(2))

This matches what its like to use node regularly such as node index.js --foo --ping=123

However when passing args directly to my built app, process.argv looks like this:

./MyApp.app/Contents/MacOS/Electron --foo --ping=123
[
  '/Users/bmann/Dev/MyApp.app/Contents/MacOS/Electron',
  '--foo',
  '--ping=123'
]

This is bad because now minimist(process.argv.slice(2)) misses the args. I get why this is happening but it is unfortunately not easy to work around, and I did not have this problem with nwjs.

I recommend using a command line arguments management system like this package. This will ensure your application can verify the input. Especially if you are depending on other human's input.

That is what I'm doing - using minimist.

That solves the problem with dasherized arguments like -v or --foo - however if your CLI tool accepts a non dashed argument this will fail.

Imagine something like gulp. If you ran gulp build in node typically the arguments would look like this:

[
  '/usr/bin/node',
  '/my-app/node_modules/.bin/gulp',
  'build'
]

However once you package your electron application the arguments will then become this:

[
  '/MyApp.app/Contents/MacOS/Electron'
  'build'
]

Do you see the problem there?

Now let's imagine your application accepts something like a path to a file as its argument. There is no way to tell the difference between what the user is providing via the CLI and what is coming from a standard node process.argv.

commented

We can probably remove my-app from process.argv in the default app, so it has the same process.argv with packaged app.

I had the same issue using yargs. This did the trick for me (assuming your command line switches always start with hyphens) :

if (process.argv[1]&&process.argv[1].indexOf('-')==0) process.argv.unshift('')

edit: i didn't read the whole thread, this doesn't solve it if you accept unhyphenated arguments...

Yes, I ran into this too. My app accepts filename arguments. I had to add a special case to remove main.js from the argument list.

(Fortunately my app doesn't deal with Javascript files, so this was a low-impact hack. Still, a hack.)

You could also define a npm startup script in your package.json that tells the app there is an extra argument not to parse :

    "scripts": {
        "start": "electron . --not-packaged"
    }

Just check before parsing process.args if it contains this special switch :

var n = process.argv.indexOf('--not-packaged')!=-1?2:1
var args = minimist(process.argv.slice(n))

Then you would use npm start -- [options] if the app is not packaged.

I'm running into the same problem. As a temporary fix, I used sed during build time to prepend a line to push the process arguments with --. e.g.

sed -i "1s/^/process.argv.unshift(\"--\");\n /" /project/build/artifacts/main.js

Everything works as expected 👍

Yargs conveniently mentions a workaround for Electron and nwjs in their documentation

commented

It is too late to change this behavior, this is going to break numerous apps. Instead I have added a process.defaultApp property to indicate whether the app is started by being passed as parameter to the default app, so people can use it to correctly handle this when parsing CLI parameters.

As of Electron 3 there is an app.isPackaged property:

  if (app.isPackaged) {
    process.argv.unshift(null)
  }

EDIT: Using yargs (see https://github.com/yargs/yargs/blob/master/docs/api.md#argv)

...

if (app.isPackaged) {
  argv = yargs.parse(process.argv.slice(1))
}