NodeJS,Windows,wmic stdin

时间:2013-08-29 14:41:06

标签: javascript windows node.js wmi wmic

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

我可以生成一个wmic.exe进程,但它不会输出任何内容或接受任何输入。但是,如果我将stdin设置为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类似的问题,但是他们只想捕获单个查询的输出,因此拥有null stdin并不重要。

更新

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

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()代替,进程根本没有响应,我甚至没有从stdout“wmic:root \ cli>”得到提示我在使用.end()时收到的。

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.exe通过wmic.stdout.on('data',fn)收到提示,并保持打开状态。但是,我无法通过代码向其发送输入,但可以直接在命令提示符窗口中输入。我键入的任何内容都已正确执行并通过节点脚本输出。再次,奇怪的是,它适用于这个管道但不是我设置和无用的,因为我想通过代码发送命令,而不是键入它们。

3 个答案:

答案 0 :(得分:3)

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

为任何应用程序实现此目的的正常方法是从管道输入它。方便的是,如果您没有指定任何其他stdio选项,NodeJS似乎默认创建管道。

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

因此,您无法发出一个命令,读取输出然后发出另一个命令。 wmic在认为已收到所有命令之前不会写输出,然后它将不再接受。

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

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会产生大量输出,但在输入完成之前没有任何内容。

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

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

答案 1 :(得分:2)

为后人......

现在可以使用ms-wmic包:

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

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

答案 2 :(得分:0)

这对我有用:

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' );