【问题标题】:NodeJS, Windows, wmic stdinNodeJS、Windows、wmic 标准输入
【发布时间】:2013-08-29 14:41:05
【问题描述】:

我在使用 NodeJS 中的 Windows 程序 WMIC.exe(用于查询 Windows Management Instrumentation)时遇到问题。

我可以生成一个 wmic.exe 进程,但它不会输出任何内容或接受任何输入。但是,如果我将标准输入设置为 null,它将正确运行并且我会收到输出。

var spawn = require('child_process').spawn;
var wmic = spawn('wmic', [], {stdio: ['ignore']});

wmic.stdout.on('data', function(data) {
  console.log('Data received:' + data);
});

wmic.on('close', function(code) {
  console.log('Spawned process ended with code: ' + code);
});

我想以交互方式使用它支持的 wmic.exe,使其保持打开状态,这样我就不必为每个 WMI 查询重复启动它。其他人在使用 wmic.exe 时也遇到过类似的问题,但他们只想捕获单个查询的输出,因此空标准输入对他们来说并不重要。

更新

如果我执行以下操作...

var spawn = require('child_process').spawn;
var wmic = spawn('wmic', []);

wmic.stdout.on('data', function(data) {
  console.log('Data received:' + data);
});

wmic.stderr.on('data', function(data) {
  console.log('Error! - ' + data);
});

wmic.on('close', function(code) {
  console.log('Spawned process ended with code: ' + code);
});

wmic.stdin.end('cpu get caption /format:csv\n');

然后它实际上会响应一个结果,提示准备好进行下一个查询,但接下来会结束该过程,显然我不能在 .end() 之后使用 .write()。将其更改为 .write() ,进程根本没有响应,我什至没有收到使用 .end() 时收到的 stdout "wmic:root\cli>" 的提示。

或者

wmic.stdin.push(null);
wmic.stdin.write('cpu/n'); // Ctrl-Z aka Windows EOF control code

如果我使用上述方法,而不是 .end() 调用,它也可以工作。但似乎如果我不继续向它抛出常量数据,该过程就会结束。

甚至

wmic.stdin.write('cpu');
wmic.stdin.write('\x1a');

这也有效,但是 wmic.exe 进程再次决定在 cpu 结果返回后退出。 :/

几乎

var wmic = spawn('wmic.exe', [], {stdio: [process.stdin, 'pipe', 'pipe']});

这行得通。该过程正确启动,因此我通过 wmic.stdout.on('data', fn) 收到来自 wmic.exe 的提示,并且它保持打开状态。但是,我无法通过代码向它发送输入,但可以直接在命令提示符窗口中输入。我输入的任何内容都会通过节点脚本正确执行和输出。再一次,奇怪的是它与这个管道一起工作,但不是我设置的任何管道,对我来说毫无用处,因为我想通过代码发送命令,而不是输入它们。

【问题讨论】:

  • 这是一个非常奇怪的问题,我已经完成了大约两个小时的测试,WMIC 始终将EOF 视为换行符(它会自动关闭流)。我还测试了产卵cmd(也有powershell)并运行wmic.exe作为命令,结果是一样的。将继续测试。
  • 同意,我沿着生成 cmd 的路线走,并使用它来启动 wmic.exe,但问题与往常一样。我觉得奇怪的是 process.stdin 会让它继续下去,这肯定是一些奇怪的事情。感谢您查看 ;)

标签: javascript windows node.js wmi wmic


【解决方案1】:

您希望以交互方式使用wmic,但由来自应用程序的输入驱动,而不是在控制台输入。

对于任何应用程序而言,实现此目的的常规方法是从管道为其提供输入。方便的是,如果您不指定任何其他 stdio 选项,NodeJS 似乎默认创建管道。

问题是wmic 在接收来自管道的输入时表现不佳。在输入完成之前它拒绝做任何事情;然后它会处理所有输入并停止查找。 wmic 认为管道关闭或收到 CTRL-Z 时输入完成。

因此您不能发出一个命令,读取输出然后发出另一个命令。 wmic 直到它认为它已经收到了所有的命令才写输出,然后它就不再接受了。

您可以在控制台上说明这个问题。 type con: | wmic 通过管道输入键盘输入,因此 wmic 进入中断模式。在下面的示例中,这后面是几个命令。请注意,在输入 CTRL-Z 之前,wmic 不会执行任何操作。

C:\>type con: | wmic
cpu get name
useraccount list brief
^Z
wmic:root\cli>cpu get name
Name
Pentium(R) Dual-Core CPU       T4500  @ 2.30GHz

wmic:root\cli>
"/?" for help, QUIT to Exit.
wmic:root\cli>useraccount list brief
AccountType  Caption                    Domain     FullName         Name
512          frog\Administrator         frog                        Administrator

wmic:root\cli>
"/?" for help, QUIT to Exit.
wmic:root\cli>
C:\>

您可能会认为(看这个例子)wmic 只是有一个大的输出缓冲区。但是,如果您打开跟踪(/TRACE:ON 作为第一个命令)wmic 会产生大量输出,但在输入完成之前什么都不会。

一种解决方案是不重定向标准输入,就像您的最后一个示例一样,因此输入来自键盘。 (注意,当 Windows 控制台应用程序从键盘接收输入时,它不会通过管道。因此您的最后一个示例没有使用管道,这就是行为不同的原因。)

然后您可以通过模拟击键向wmic 提供输入。 Answers to this question 建议了几种方法:使用 SendKeys 或发送 WM_KEYUP 消息。这不是一个很好的解决方案。

【讨论】:

    【解决方案2】:

    为了后代……

    现在可以通过使用 ms-wmic 包来实现:

    这完全绕过了必须直接与 CLI 交互,并允许您通过预设 API 处理 WMIC


    但您在上面的示例中尝试使用WMIC 的具体内容也由windows-cpu 包处理:

    【讨论】:

      【解决方案3】:

      这对我来说是这样的:

      var spawn = require('child_process').spawn;
      var wmic = spawn('wmic', []);
      
      wmic.stdout.on('data', function(data) {
        console.log('Data received: [[' + data + ']]');
      });
      
      wmic.stderr.on('data', function(data) {
        console.log('Error! - ' + data);
      });
      
      wmic.on('close', function(code) {
        console.log('Spawned process ended with code: ' + code);
      });
      
      wmic.stdin.end( 'cpu get caption /format:csv' );
      

      【讨论】:

        猜你喜欢
        • 2017-09-27
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-02
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        相关资源
        最近更新 更多