【问题标题】:Run MSI package from nodejs app从 nodejs 应用程序运行 MSI 包
【发布时间】:2016-02-12 14:42:59
【问题描述】:

我想从 nodeJS 应用程序运行 mongoDB MSI 包。我试图按照this 问题的答案进行操作,但它给了我以下错误:

internal/child_process.js:298
throw errnoException(err, 'spawn');
^
Error: spawn UNKNOWN
    at exports._errnoException (util.js:837:11)
    at ChildProcess.spawn (internal/child_process.js:298:11)
    at exports.spawn (child_process.js:339:9)
    at exports.execFile (child_process.js:141:15)
    at C:\_PROJECTs\nodejs\automation\mongoDB-setup\auto-setup.js:34:5
    at C:\_PROJECTs\nodejs\automation\mongoDB-setup\lib\file.js:31:5
    at C:\_PROJECTs\nodejs\automation\mongoDB-setup\lib\file.js:20:5
    at FSReqWrap.oncomplete (fs.js:82:15)

当尝试简单的 EXE 文件(例如 puttygen.exe)时,它可以工作。

这是我拥有的代码的相关部分:

'use strict'
const os = require('os'),
      path = require('path'),
      setup = require('child_process').execFile;

const fileName = 'mongodb.msi';
//const fileName = 'puttygen.exe';
const dest = path.join(os.homedir(), fileName);

// run the installation
setup(dest, function(err, data) {  
  console.log(err);                      
});

我不确定 execFile 是否也是 MSI 软件包的正确方式。

【问题讨论】:

    标签: node.js windows-installer


    【解决方案1】:

    我建议在这种情况下使用spawn。 (有关更多说明,请参阅节点 js 文档)。在 win64 上,我认为您需要使用参数生成命令行,否则 child_process.js 会为您执行此操作(对于 unix 也是如此)。

    这是您的案例(非 ES6)的示例:

    var os = require('os'),
      path = require('path'),
      setup = require('child_process').spawn;
    
    //1)uncomment following if you want to redirect standard output and error from the process to files
    /*
    var fs = require('fs');
    var out = fs.openSync('./out.log', 'a');
    var err = fs.openSync('./out.log', 'a');
    */
    var fileName = 'mongodb.msi';
    
    //spawn command line (cmd as first param to spawn)
    var child = spawn('cmd', ["/S /C " + fileName], { // /S strips quotes and /C executes the runnable file (node way)
      detached: true, //see node docs to see what it does
      cwd: os.homedir(), //current working directory where the command line is going to be spawned and the file is also located
      env: process.env
      //1) uncomment following if you want to "redirect" standard output and error from the process to files
      //stdio: ['ignore', out, err]
    });
    
    //2) uncomment following if you want to "react" somehow to standard output and error from the process
    /*
    child.stdout.on('data', function(data) {
      console.log("stdout: " + data);
    });
    
    child.stderr.on('data', function(data) {
      console.log("stdout: " + data);
    });
    */
    
    //here you can "react" when the spawned process ends
    child.on('close', function(code) {
      console.log("Child process exited with code " + code);
    });
    
    // THIS IS TAKEN FROM NODE JS DOCS
    // By default, the parent will wait for the detached child to exit.
    // To prevent the parent from waiting for a given child, use the child.unref() method,
    // and the parent's event loop will not include the child in its reference count.
    child.unref();
    

    希望它有所帮助:) 如果您想要 win32 或 UNIX 版本,它看起来会有些不同,请再次查看文档以获取更多信息,或发布另一个请求。 另请参阅child_process.js 的源代码。

    【讨论】:

      【解决方案2】:
      const dest = "cmd /c " + path.join(os.homedir(), fileName);
      

      【讨论】:

      • 对不起,我不明白。这种改变应该实现什么?尝试时出现以下错误:[Error: spawn cmd /cC:\Users\bulavjan\mongodb.msi ENOENT] code: 'ENOENT', errno: 'ENOENT', syscall: 'spawn cmd /cC:\\Users\\bulavjan\\mongodb.msi', path: 'cmd /cC:\\Users\\bulavjan\\mongodb.msi', spawnargs: [], cmd: 'cmd /cC:\\Users\\bulavjan\\mongodb.msi'
      • 你错过了 /c 后面的空格字符
      • 真 :)。现在我有了:const dest = "cmd /c " + path.join(os.homedir(), fileName);,但结果还是一样:[Error: spawn cmd /c C:\Users\bulavjan\mongodb.msi ENOENT]
      • 您的 msi 文件可能是从网上下载的,但尚未解锁。在浏览器中找到 .msi 数据包,右键单击它,然后按“常规”选项卡底部的“取消阻止”按钮。
      【解决方案3】:

      运行 .msi 文件的最佳方法是使用 Windows 配置的命令行工具,称为 msiexec。 所以截取的代码如下

      import * as os from 'os';
      import { spawn } from 'child_process';
      
      // /quiet does installing in background process. Use docs to find more. 
      export const runMSI = (msiName: string, args?: string[]) => {
          const childProcess = spawn('msiexec', [`/i ${msiName} /quiet`], {
              detached: false,
              cwd: os.homedir(),
          });
      
          childProcess.stdout.on('data', (data) => {
              console.log('STDOUT: ', data.toString());
          });
      
          childProcess.stderr.on('data', (data) => {
              console.log('STDERR: ', data.toString());
          });
      
      
          childProcess.on('close', (code: number) => {
              console.log('Child exited with code ' + code);
          });
      };
      

      【讨论】:

        【解决方案4】:

        我来自未来>> 2020-jul-29。 nodejs 文档建议改用execexecFile 函数。

        为方便起见,child_process 模块为 child_process.spawn() 和 child_process.spawnSync() 提供了一些同步和异步替代方案。这些替代方案中的每一个都在 child_process.spawn() 或 child_process.spawnSync() 之上实现。 https://nodejs.org/api/child_process.html#child_process_spawning_bat_and_cmd_files_on_windows

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-24
          • 1970-01-01
          • 2015-12-12
          • 1970-01-01
          相关资源
          最近更新 更多