Как выполнить локально установленное приложение Node.js с помощью child_process.spawn ()? - PullRequest
1 голос
/ 24 июня 2019

Я хочу выполнить приложение Electron по child_process.spawn:

import ChildProcess, {ChildProcess as ChildProcess__type} from 'child_process';
const childProcess: ChildProcess__type = ChildProcess.spawn(
        'electron',
        ['ProjectInitializer__ElectronMain.js'],
        { cwd: __dirname } // current project root
    );

Я получил Error: spawn electron ENOENT ошибку.Электрон был установлен локально, AFAIK - хорошая практика.Кроме того, electron ProjectInitializer__ElectronMain.js работает, чтобы выполнить эту консольную команду из каталога моего проекта.

Следуя часто задаваемым ошибкам ENOENT, руководство по отладке ошибок , я получил причину: среди каталогов нетprocess.env.PATH, включая electron.

Я знаю немного о переменной PATH, поэтому не могу ответить, что должно быть в этой переменной, а что нет.Но я хочу спросить: как выполнять локально установленные (в node_modules) приложения Node.js (например, electron)?

Кстати, execa , который известенкак улучшено child_process запускает электрон без ошибок (обновление: версия 2.xx уже не запускается):

import executeExternalCommand, { ExecaReturnValue } from 'execa';

try {
  await executeExternalCommand(
      'electron',
      ['ProjectInitializer__ElectronMain.js'],
      { cwd: __dirname }
  );
} catch (error) {
  console.error(error);
}

Каким-то образом, благодаря { cwd: __dirname }, execa v 1.x.x знает, где следует найтиэлектрон.К сожалению, execa имеет слишком маленькое сообщество и небольшую документацию, поэтому перестал его использовать.

Дополнительная информация

Как мне запустить этот скрипт Node.js, который имеет параметр spawn

По команде my-library init, которую я создал.

В package.json:

"bin": {
  "my-library": "bin/my-library"
}

В bin/my-library (без расширения имени файла):

#!/usr/bin/env node

require('../CLI').interpretConsoleCommandAndExecute(process.argv);

В CLI.js я анализирую консольную команду, и если это my-library init, я попытаюсь выполнить

const childProcess: ChildProcess__type = ChildProcess.spawn(
   'electron',
   [ 'ProjectInitializer__ElectronMain.js' ],
   { cwd: __dirname }
);

console.log (process.env) output

Ниже приведен вывод для встроенной консоли PhpStorm, однако в других консолях, например, в cmder, вывод отличается.

{ FPS_BROWSER_APP_PROFILE_STRING: 'Internet Explorer',
  CommonProgramFiles: 'C:\\Program Files\\Common Files',
  PROMPT: '$P$G',
  SESSIONNAME: 'Console',
  COMPUTERNAME: 'MSI',
  OneDriveConsumer: 'D:\\OneDrive',
  __INTELLIJ_COMMAND_HISTFILE__:
   'C:\\Users\\i\\.PhpStorm2019.1\\config\\terminal\\history\\history-34',
  SystemDrive: 'C:',
  NUMBER_OF_PROCESSORS: '12',
  LOGONSERVER: '\\\\MSI',
  TEMP: 'C:\\Users\\i\\AppData\\Local\\Temp',
  TMP: 'C:\\Users\\i\\AppData\\Local\\Temp',
  HOMEPATH: '\\Users\\i',
  PATHEXT: '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JSE;.WSF;.WSH;.MSC',
  USERNAME: 'i',
  ProgramFiles: 'C:\\Program Files',
  USERDOMAIN_ROAMINGPROFILE: 'MSI',
  LOCALAPPDATA: 'C:\\Users\\i\\AppData\\Local',
  TERMINAL_EMULATOR: 'JetBrains-JediTerm',
  PROCESSOR_IDENTIFIER: 'Intel64 Family 6 Model 158 Stepping 10, GenuineIntel',
  DriverData: 'C:\\Windows\\System32\\Drivers\\DriverData',
  APPDATA: 'C:\\Users\\i\\AppData\\Roaming',
  ALLUSERSPROFILE: 'C:\\ProgramData',
  USERDOMAIN: 'MSI',
  OS: 'Windows_NT',
  PROCESSOR_LEVEL: '6',
  ProgramData: 'C:\\ProgramData',
  ComSpec: 'C:\\Windows\\system32\\cmd.exe',
  PROCESSOR_ARCHITECTURE: 'AMD64',
  FPS_BROWSER_USER_PROFILE_STRING: 'Default',
  SystemRoot: 'C:\\Windows',
  PROCESSOR_REVISION: '9e0a',
  OneDrive: 'D:\\OneDrive',
  PSModulePath:
   'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules',
  PATH:
   'D:\\PhpStorm\\InHouseDevelopment\\my-library\\node_modules\\.bin;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Program Files\\Docker\\Docker\\Resources\\bin;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Program Files
\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Pro
gram Files\\Intel\\WiFi\\bin\\;C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files (x86)\\Intel\\I
ntel(R) Management Engine Components\\IPT;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files (x86)\\Common Files\\Acronis\\VirtualFile\\;C:\\Program Files (x86)\\Common Files\\Acronis\\VirtualFile64\\;C:\\Program Files (x86)\\Com
mon Files\\Acronis\\FileProtector\\;C:\\Program Files (x86)\\Common Files\\Acronis\\FileProtector64\\;C:\\Program Files (x86)\\Common Files\\Acronis\\SnapAPI\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Git\\cmd;C:\\Program Files (x86)\\Yarn\\bin\\;C:\\Users\\t
okug\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\i\\AppData\\Roaming\\npm;C:\\Users\\i\\AppData\\Local\\Yarn\\bin;C:\\texlive\\2019\\bin\\win32',
  'ProgramFiles(x86)': 'C:\\Program Files (x86)',
  USERPROFILE: 'C:\\Users\\i',
  windir: 'C:\\Windows',
  ProgramW6432: 'C:\\Program Files',
  configsetroot: 'C:\\Windows\\ConfigSetRoot',
  'CommonProgramFiles(x86)': 'C:\\Program Files (x86)\\Common Files',
  PUBLIC: 'C:\\Users\\Public',
  HOMEDRIVE: 'C:',
  CommonProgramW6432: 'C:\\Program Files\\Common Files' }

Попытка выполнить ChildProcess.spawn ('env')

В консоли Php Strorm вызывает знакомую Error: spawn env ENOENT.

Ответы [ 2 ]

1 голос
/ 29 июня 2019

Как обсуждалось в чате, ошибка, которую вы получаете, обычно вызвана тем, что исполняемый файл, который вы пытаетесь запустить, недоступен

Теперь существует несколько причин, по которым исполняемый файл может быть недоступен

  1. Исполняемый файл вообще отсутствует в системе
  2. Исполняемый файл есть, но не в папках, определенных системной PATH переменной
  3. Исполняемый файл естьв текущем каталоге, но контекст каталога, в котором выполняется процесс, отличается

Чтобы исправить #1 и #2, вы просто устанавливаете исполняемый файл глобально в системе PATH

Для исправления #3 вы можете сделать две вещи.Добавьте путь для текущего каталога ({ cwd: __dirname}), а также относительный путь к исполняемому файлу

const childProcess: ChildProcess__type = ChildProcess.spawn( 
Path.resolve(__dirname, 'node_modules/.bin/electron'), 
[ Path.resolve(__dirname, 'ProjectInitializer__ElectronMain.js') ], 
{ cwd: __dirname} 
); 

или

const childProcess: ChildProcess__type = ChildProcess.spawn( 
'./node_modules/.bin/electron'), 
[ Path.resolve(__dirname, 'ProjectInitializer__ElectronMain.js') ], 
{ cwd: __dirname} 
); 

или

const childProcess: ChildProcess__type = ChildProcess.spawn( 
'node_modules/.bin/electron', 
[ './ProjectInitializer__ElectronMain.js' ], 
{ cwd: __dirname} 
); 

В случаевы решаете переопределить переменную среды PATH, вы можете сделать это, передав параметры env с большим количеством значений

const childProcess: ChildProcess__type = ChildProcess.spawn( 
'node_modules/.bin/electron', 
[ './ProjectInitializer__ElectronMain.js' ], 
{ cwd: __dirname, env: {....}} 
); 

Вы можете использовать существующие переменные среды из process.env, а затем обновить их, ипередать его env параметру

0 голосов
/ 26 июня 2019

вполне вероятно, что вам нужно указать полный путь к электронной команде, поскольку она не находится на вашем пути.

Если вы запускаете свой скрипт из корня проекта, электрон, вероятно, находится в ./node_modules/.bin/electron, если они упаковали приложение для запуска таким образом.

Я бы предположил, что ваша альтернативная библиотека по умолчанию проверяет node_modules.

Альтернативой может быть обеспечение того, что электрон находится на вашем пути, но это требует обновления конфигурации вашей системы, что было бы странно для библиотеки.

Редактировать: пример вызова с путем:

const childProcess: ChildProcess__type = ChildProcess.spawn(
   'node_modules/.bin/electron',
   [ 'ProjectInitializer__ElectronMain.js' ],
   { cwd: __dirname }
);

Я бы также добавил немую запись в журнал процесса, чтобы вы знали, почему процесс завершился неудачей:

function log(data) {
    console.log("" + data)
}
child_process.stdout.on('data', log)
child_process.stderr.on('data', log)
child_process.on('close', log)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...