[英]NodeJS, Windows, wmic stdin
I've having a problem with the Windows program WMIC.exe (used for querying Windows Management Instrumentation), from within NodeJS. 我在NodeJS中遇到了Windows程序WMIC.exe(用于查询Windows Management Instrumentation)的问题。
I can spawn a wmic.exe process, but it'll not output anything or accept any input. 我可以产生一个wmic.exe进程,但它不会输出任何内容或接受任何输入。 However, if I set the stdin to null it'll run correctly and I'll receive output.
但是,如果将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);
});
I want to use wmic.exe interactively, which it supports, keeping it open so I don't have to repeatedly start it for each WMI query. 我想交互使用它支持的wmic.exe,使其保持打开状态,因此我不必为每个WMI查询重复启动它。 Others have had similar problems with wmic.exe, but they only wanted to capture output for a single query, so having a null stdin doesn't matter to them.
其他人在wmic.exe上也有类似的问题,但是他们只想捕获单个查询的输出,因此拥有空的stdin对他们来说并不重要。
Update 更新
If I do the following... 如果我执行以下操作...
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');
Then it'll actually respond with a result, prompt back ready for the next query but next ends the process and obviously I can't use .write() after .end(). 然后,它实际上会响应一个结果,提示您准备好进行下一个查询,但接下来将结束该过程,显然我不能在.end()之后使用.write()。 Changing it to a .write() instead, process doesn't respond at all and I don't even get the prompt from stdout "wmic:root\\cli>" that I receive when using .end().
相反,将其更改为.write(),进程根本不响应,我什至没有收到使用.end()时收到的标准输出“ wmic:root \\ cli>”的提示。
Or 要么
wmic.stdin.push(null);
wmic.stdin.write('cpu/n'); // Ctrl-Z aka Windows EOF control code
If I use the above, instead of the .end() call, it'll also work. 如果我使用上面的方法,而不是.end()调用,它也将起作用。 But it seems that if I don't keep throwing constant data at it, the process ends.
但是看来,如果我不不断地向其抛出恒定数据,则过程结束。
Or even 甚至
wmic.stdin.write('cpu');
wmic.stdin.write('\x1a');
This works too, but yet again, the wmic.exe process decides to exit after the cpu results are returned. 这也可行,但是同样,在返回cpu结果之后,wmic.exe进程决定退出。 :/
:/
Almost 几乎
var wmic = spawn('wmic.exe', [], {stdio: [process.stdin, 'pipe', 'pipe']});
This works. 这可行。 The process starts up correctly so I receive the prompt from wmic.exe through wmic.stdout.on('data', fn) and it stays open.
该过程正确启动,因此我通过wmic.stdout.on('data',fn)从wmic.exe收到了提示,它保持打开状态。 However, I'm unable to send input to it via code but can type directly into the command prompt window.
但是,我无法通过代码将输入发送给它,但是可以直接在命令提示符窗口中键入。 Anything I type is correctly executed and output via the node script.
我键入的任何内容都可以正确执行并通过节点脚本输出。 Again, weird that it works with this pipe but not any I set and useless to me as I want to send commands via code, not typing them.
再次,奇怪的是它与该管道一起工作,但是我设置的任何管道都没有,对我来说毫无用处,因为我想通过代码发送命令,而不是键入命令。
You want to use wmic
interactively, but driven by input from an application rather than input typed at the console. 您希望交互使用
wmic
,但要由应用程序的输入而不是在控制台上键入的输入来驱动。
The normal way to achieve this for any application is to feed it input from a pipe. 对于任何应用程序,实现此目标的正常方法是从管道中馈入输入。 Conveniently, NodeJS appears to create a pipe by default if you don't specify any other
stdio
option. 方便地,如果您未指定任何其他
stdio
选项,则NodeJS似乎默认情况下会创建管道。
The problem is that wmic
behaves badly when it is receiving input from a pipe. 问题是,
wmic
从管道接收输入时表现不佳。 It refuses to do anything until the input is complete; 在输入完成之前,它拒绝执行任何操作。 it then processes all the input and stops looking for any more.
然后,它将处理所有输入,并停止寻找更多内容。
wmic
thinks that the input is complete when the pipe is closed or it receives a CTRL-Z. 当管道关闭或收到CTRL-Z时,
wmic
认为输入已完成。
Hence you cannot issue one command, read the output and then issue another command. 因此,您不能发出一个命令,不能读取输出,然后发出另一个命令。
wmic
doesn't write output until it thinks it has received all the commands, and then it won't accept any more. 在认为自己已收到所有命令之后,
wmic
才写输出,然后它将不再接受。
You can illustrate this problem at the console. 您可以在控制台上说明此问题。
type con: | wmic
type con: | wmic
puts keyboard input through a pipe so wmic
goes into its broken mode. type con: | wmic
通过管道放置键盘输入,因此wmic
进入其损坏模式。 In the example below this is followed by a couple of commands. 在下面的示例中,后面是几个命令。 Note that
wmic
does nothing until CTRL-Z
is entered. 注意,在输入
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:\>
You might think (looking at this example) that wmic
just has a large output buffer. 您可能会认为(看这个例子)
wmic
只有一个很大的输出缓冲区。 However, if you turn on tracing ( /TRACE:ON
as the first command) wmic
produces reams of output, but nothing before the input is complete. 但是,如果打开跟踪(第一个命令
/TRACE:ON
),则wmic
会生成大量输出,但是在输入完成之前什么也没有。
A solution is to not redirect the standard input, like your final example, so the input is coming from the keyboard. 一种解决方案是不像最终示例一样重定向标准输入,因此输入来自键盘。 (NB when a Windows console application receives input from the keyboard it is not coming through a pipe. Hence your final example is not using a pipe, which is why is behaves differently.)
(注意,当Windows控制台应用程序从键盘接收到输入时,它不是通过管道输入的。因此,您的最后一个示例未使用管道,这就是行为不同的原因。)
You can then supply input to wmic
by simulating keystrokes. 然后,您可以通过模拟击键为
wmic
提供输入。 Answers to this question suggest a couple of methods: either using SendKeys
or by sending WM_KEYUP
messages. 该问题的答案提出了两种方法:使用
SendKeys
或通过发送WM_KEYUP
消息。 This is not a great solution. 这不是一个很好的解决方案。
For posterity... 为了后代...
ms-wmic
package: ms-wmic
包来实现: This completely bypasses having to directly interact with the CLI, and allows you to deal with WMIC
through a preset API. 这完全避免了直接与CLI交互的麻烦,并允许您通过预设的API处理
WMIC
。
But the specific thing you tried to use WMIC
for in your example above, is also handled by the windows-cpu
package: 但是,您在上面的示例中尝试使用
WMIC
的特定操作也由windows-cpu
软件包处理:
That's how it worked for me: 那对我来说是这样的:
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' );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.