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