简体   繁体   English

NodeJS,Windows,Wmic标准输入

[英]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... 为了后代...

This is now possible by using the 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM