【问题标题】:Batch WMIC redirecting output and wrapping into variable批量 WMIC 重定向输出并包装到变量中
【发布时间】:2012-10-18 22:18:41
【问题描述】:

我正在尝试使用 WMIC 删除我们旧打印服务器上的一些旧打印机

如果我在命令行中使用下面的语法,它就可以工作

WMIC 打印机将“SERVERNAME LIKE '%%OLDSERVERNAME%%'”删除

有人问我是否可以让它替换打印机或更新它们,以免帮助台收到“如何添加我的打印机”电话

我尝试使用 SET 进行一些变体来设置 SERVERNAME 的属性,它似乎正在处理,但没有任何变化,并且执行 GET 仍然显示旧值。

所以我想我可以做一个 FOR /F 循环,将打印机的名称 (sharename) 包装在一个变量中,然后在删除有问题的打印机后使用另一个命令重新创建打印机。

这是我的脚本

@ECHO

ECHO Gathering Installed Printer Information...

FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO SET PRINTERNAME=%%A

ECHO %PRINTERNAME%

所以你会认为你会得到一个很好的变量中的值,但不,我打开了回显,看起来变量一旦被捕获就会被设置回 null

我的输出看起来像这样......

FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO SET PRINTERNAME=%%A

SET PRINTERNAME=nameofprinter

SET PRINTERNAME=

ECHO

ECHO is on.

很想知道为什么它似乎在倾倒字符串。

Powershell 和 VBScript 也不是不可能的选择,我对两者都很熟悉,只是这似乎可行,我真的不想重新开始。

【问题讨论】:

  • 将您的 WMIC 语句放在 FOR 循环中只会给 %%A 打印机的值 - 它无法设置它,因为您的 WMIC 命令正在执行 GET,而不是 SET。如果没有 FOR 循环,请尝试执行相同的 WMIC 命令,但将 GET 替换为 SET。但是,核心问题是您要更新打印驱动程序和名称,这需要比您这里更多的脚本。
  • @Lizz - 在这种情况下,Set 不是 WMIC 命令,它是用于设置环境变量的内部命令处理器命令。如果您查看他的输出,您会看到 4 个已执行的命令,而预期只有两个。具体来说,您会看到变量 PRINTERNAME 设置为 nameofprinter,然后设置为空,然后在没有数据的情况下调用命令 ECHO,然后您会看到一个空的 ECHO 命令的结果,它是“ECHO 开启。”,因为他没有打开ECHO OFF,因为他正在调试。唯一可能的结果是ECHO is off.,但前提是他之前设置了@echo off 命令。

标签: batch-file wmi wmi-query wmic


【解决方案1】:

WMIC 正在返回两行,一行带有打印机名称,另一行为空。
解决这个问题的方法是测试空行。

ECHO Gathering Installed Printer Information...
FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO if not "%%A"=="" SET PRINTERNAME=%%A
ECHO %PRINTERNAME%

【讨论】:

  • WMIC 命令为 GET 时如何更新或删除打印机?
  • @Lizz - 它没有。我专门回答了他的问题“我会喜欢一些关于为什么它似乎在倾倒字符串的想法。”如果他在问题的最开头所说的是真的,那么删除打印机将是一个添加WMIC PRINTER WHERE "SERVERNAME LIKE '%PRINTERNAME%'" DELETE的简单问题。
  • 猜猜不止一个问题。感谢您的澄清:)
  • WMIC PRINTER WHERE "SERVERNAME LIKE '%PRINTERNAME%'" DELETE" 就像一个魅力,我已经有一个脚本可以做到这一点,这里的最终目标是捕获打印机的价值并暂时存储它,然后我会运行删除,但之后,我会使用类似“RUNDLL32.exe PrintUI.DLL,PrintUIEntry /IN /cServername /n\\Servername\Printername” 但问题是它正在转储值,我研究发布后多一点,一个线程建议此命令以 unicode 输出,而不是 ASCII
【解决方案2】:

你要找的是这个:

for /f "skip=2 tokens=2 delims=," %%A in ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename /format:csv') DO SET PRINTERNAME=%%A
ECHO %PRINTERNAME%

解释:

wmic 的 unicode 输出包括一个由 FOR /F 捕获的回车,这是您不想要的,因为这意味着“输入”成为变量 (%%A) 的一部分,并且它还包含一个空行,将再次输出到 %%A。

我的示例执行以下操作: /format:cvs -- 将输出一个逗号分隔的输出,以便我们可以使用分隔符捕获, skip=2 -- 将跳过开头的空行并跳过 csv 的标题行。 tokens=2 -- csv 输出包含名称、值作为输出,但您只需要值,即第二个标记。

顺便说一句,因为我们不再将空格作为分隔符包含在内,它甚至应该在值中使用空格。试一试。

【讨论】:

    【解决方案3】:

    我绕过了 UNICODE 回车(这确实是这里的问题),如下所示:

    @echo off
    FOR /F "usebackq tokens=1,2 delims==" %%A IN (`wmic %* /VALUE ^| findstr "="`) DO (call :OUTPUT %%A "%%B")
    exit /b
    
    :OUTPUT
    echo %1=%2
    

    另存为“wmi.bat” 并像这样执行您的查询:

    wmi.bat printer where 'name like "HP%"' get name
    

    我的输出如下所示:

    Name="HP1C0BCA (HP Officejet Pro 276dw MFP)"
    Name="HP Officejet Pro L7500 Series"
    Name="HP Officejet Pro 276dw MFP PCL 6"
    

    您可以想象如何使用它。 "%%B" 部分将 /VALUE 的所有输出(包括空格)放入 %2 %%A 捕获对象 i​​d,它变成 %1,如果您使用它来记录来自 WMI 的各种信息,这很方便。再也不用担心 Unicode 回车了。

    这种方法的最大优点是你有一个聪明的批处理文件,它克服了在脚本中使用它时 wmic 给你的限制,你可以将它用于任何事情。 您可以将批处理文件的 STDOUT 用作其他任何参数,甚至可以用作 wmic 的输入!

    【讨论】:

    • 谢谢,但是你迟到了一年,我最终用 vbscript 编写了整个东西,利用 Win32_printers 中的 2 个 WMI 对象,并且能够查询我需要的数据,以及稍后关于将打印机从一个 UNC 路径自动迁移到新路径,作为我针对不同标准通过选择案例运行的功能的一部分,总而言之,我从我的日志中迁移了大约 60,000 个组合的 UNC 打印机映射。
    【解决方案4】:

    最安全和通用的变体是嵌套另一个 for /F 循环,如下所示:

    for /F "skip=1 usebackq delims=" %%A in (`
        wmic Printer where 'Servername like "%%printaz1%%"' get ShareName
    `) do for /F "delims=" %%B in ("%%A") do set "PRINTERNAME=%%A"
    

    问题在于 wmic 命令的 Unicode 输出以及 for /F 对 ANSI 文本的不良转换,这会留下一些孤立的回车字符,这反过来又会让一些额外的行显示为非空。第二个for /F 循环消除了这些转换伪影。

    我还将tokens=1 选项替换为delims=,以免在第一个空格处截断返回的项目。

    也可以看看dbenham用户的以下相关回答:

    【讨论】:

      【解决方案5】:
      @ECHO
      
      ECHO Gathering Installed Printer Information...
      
      FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO (
        SET PRINTERNAME=%%A
        goto end
      ) 
      :end
      ECHO %PRINTERNAME%
      

      【讨论】:

      • 欢迎来到 Stack Overflow!通常,当您在答案中包含一段代码时,最好对代码的作用进行某种解释。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2012-07-23
      • 2014-10-31
      • 1970-01-01
      相关资源
      最近更新 更多