wshShell和WMIC如何在批处理中一起运作?

3
我试图使用这里找到的方法Scrollable Lists in .bat Files为批处理文件创建可滚动列表。 感谢https://stackoverflow.com/users/778560/aacini
当我尝试逐行添加我的常规批处理代码时,我发现当我使用WMIC时,该解决方案不起作用。这是什么原因,是否有简单的解决方案?您可以运行下面的代码,然后取消注释WMIC行,看看它将不再起作用。
编辑:我正在使用Windows 7
谢谢!
@if (@CodeSection == @Batch) @then
@echo off
setlocal EnableDelayedExpansion
color F0


::FOR /F "tokens=2 delims==" %%A IN ('WMIC csproduct GET Name /VALUE ^| FIND /I "Name="') DO SET machine=%%A


Echo Reset or Continue
Set MenuOptions=RESET Continue
call :ShowMenu

pause
exit

:ShowMenu
set numOpts=0
for %%a in (%MenuOptions%) do (
   set /A numOpts+=1
   set "option[!numOpts!]=%%a"
)
rem Clear previous doskey history
doskey /REINSTALL
rem Fill doskey history with menu options
cscript //nologo /E:JScript "%~F0" EnterOpts
for /L %%i in (1,1,%numOpts%) do set /P "var="

rem Send a F7 key to open the selection menu
cscript //nologo /E:JScript "%~F0"
set /P "MenuSelected=Option Selected: "
echo/
@end
var wshShell = WScript.CreateObject("WScript.Shell"),
    envVar = wshShell.Environment("Process"),
    numOpts = parseInt(envVar("numOpts"));

if ( WScript.Arguments.Length ) {
   // Enter menu options
   for ( var i=1; i <= numOpts; i++ ) {
      wshShell.SendKeys(envVar("option["+i+"]")+"{ENTER}");
   }
} else {
   // Enter a F7 to open the menu
   wshShell.SendKeys("{F7}");
}

我唯一看到的导致调用“wmic”不起作用的原因是,也许你的批处理文件被命名为“wmic.bat”或“wmic.cmd”,并且它正在调用自身。另外请注意,在“@end”行之前缺少“goto :eof”。 - MC ND
我可以确认这种改变的行为,即使用另一个可执行文件而不是“wmic”也不会出现菜单。例如,在Windows 8.1上测试了“findstr /N“wshShell”%~f0”。 - JosefZ
@JosefZ,已在Windows 10 64和Windows 7 32上进行了测试。在两种情况下,发布的代码都显示了菜单,但是doskey /reinstall无论是否使用wmic都不能清除先前命令的历史记录。 - MC ND
再次测试了一些可执行文件,甚至从cmd提示符中调用批处理。 D:\ bat \ SO \ 40165693.bat不会显示菜单,而CMD / C D:\ bat \ SO \ 40165693.bat可以完美运行... @MCND我可以确认,当在第二次及以后运行D:\ bat \ SO \ 40165693.bat时(没有WMIC),doskey / reinstall不会清除先前命令的历史记录。 - JosefZ
我已经编辑了帖子,包括我使用的是Windows 7。我还添加了goto:eof,这似乎有所帮助,直到我更改了代码为:FOR /F "tokens=2 delims==" %%A IN ('WMIC csproduct GET Name /VALUE ^| FIND /I "Name="') DO SET machine=%%A。但它又不起作用了。再次感谢大家的帮助。 - Wajo357
1个回答

1

SendKeys Method发送一个或多个按键到活动窗口。不幸的是,Sendkeys()有时会失败,通常是由于焦点时间问题造成的,这两个问题都很棘手且难以解决。我尝试了pausetimeout,尝试了各种组合的WshShell.AppActivate,但都没有成功...

最终,我发现问题出在通过doskey /REINSTALL命令清除先前的doskey历史记录中:它安装了一个新的doskey副本。我可以推荐更直观(且不太侵入性)的方法来清除doskey命令历史缓冲区:

doskey /ListSize=0
doskey /ListSize=50

奖励: FOR循环解释。

  • 外部%%A循环用于检索name属性;
  • 内部%%a循环用于删除返回值中的结尾回车符wmic行为:每个输出行都以0x0D0D0A<CR><CR><LF>)结尾,而不是常见的0x0D0A<CR><LF>)。

来源: Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem

工作脚本 (Windows 8.1 64位):

@if (@CodeSection == @Batch) @then
@echo OFF
setlocal EnableDelayedExpansion
REM color F0

  FOR /F "tokens=2 delims==" %%A IN ('
    WMIC csproduct GET Name /VALUE ^| FIND /I "Name="
  ') DO FOR %%a in ("%%~A") DO SET "_machine=%%~a"

Echo Reset or Continue %_machine%
Set "MenuOptions=%_machine% RESET Continue"  expanded merely for debugging purposes
call :ShowMenu

REM pause
exit /B

:ShowMenu
set numOpts=0
for %%a in (%MenuOptions%) do (
   set /A numOpts+=1
   set "option[!numOpts!]=%%a"
)
rem Clear previous doskey history
REM this causes problems: doskey /REINSTALL
doskey /ListSize=0
doskey /ListSize=50
rem Fill doskey history with menu options
cscript //nologo /E:JScript "%~F0" EnterOpts
for /L %%i in (1,1,%numOpts%) do set /P "var="

rem Send a F7 key to open the selection menu
cscript //nologo /E:JScript "%~F0"
set /P "MenuSelected=Option Selected: "
echo/
goto :eof
@end
var wshShell = WScript.CreateObject("WScript.Shell"),
    envVar = wshShell.Environment("Process"),
    numOpts = parseInt(envVar("numOpts"));

if ( WScript.Arguments.Length ) {
   // Enter menu options
   for ( var i=1; i <= numOpts; i++ ) {
      wshShell.SendKeys(envVar("option["+i+"]")+"{ENTER}");
   }
} else {
   // Enter a F7 to open the menu
   wshShell.SendKeys("{F7}");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接