Пакетное перенаправление вывода WMIC и перенос в переменную

Я пытаюсь использовать WMIC для удаления некоторых старых принтеров на наших старых серверах печати.

если я использую приведенный ниже синтаксис из командной строки, он работает

ПРИНТЕР WMIC, ГДЕ "ИМЯ СЕРВЕРА, КАК '%% OLDSERVERNAME %%'" УДАЛИТЬ

Меня попросили посмотреть, могу ли я заставить его заменить принтеры или обновить их, чтобы избавить службу поддержки от звонков "как мне добавить мой принтер"

Я попробовал несколько вариантов с SET, чтобы установить свойства для SERVERNAME, кажется, что он обрабатывается, но ничего не меняется, и выполнение GET по-прежнему показывает старое значение.

поэтому я решил, что могу выполнить цикл FOR / F, обернуть имя принтера (общее имя) в переменную, а затем использовать другую команду для воссоздания принтеров после того, как виновные принтеры будут удалены.

вот мой сценарий

@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%

так что вы могли бы подумать, что получите значение, все завернутое в красивую переменную, которую можно использовать по своему усмотрению, но нет, я включил эхо, и кажется, что переменная возвращается к нулю, как только она захватывается

мой вывод выглядит так ...

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 тоже не исключены, я знаком с обоими, просто это казалось возможным, и я действительно не хочу начинать все сначала.


person Matt Hamende    schedule 18.10.2012    source источник
comment
Помещение вашего оператора WMIC в цикл FOR дает только %% A значение принтера - он не может его установить, потому что ваша команда WMIC выполняет GET, а не SET. Без цикла FOR попробуйте выполнить ту же команду WMIC, но замените GET на SET. Однако основная проблема заключается в том, что вы хотите обновить драйвер принтера и имя, для чего требуется гораздо больше скриптов, чем то, что у вас здесь.   -  person Lizz    schedule 28.10.2012
comment
@Lizz - Set в данном случае не является командой WMIC, это внутренняя команда командного процессора для установки переменной окружения. Если вы посмотрите на его вывод, вы увидите 4 выполненных команды, из которых ожидаются только две. В частности, вы видите, что для переменной PRINTERNAME установлено значение nameofprinter, затем установлено значение "Ничего", затем команда ECHO вызывается без данных, затем вы видите результат пустой команды ECHO, то есть ECHO включен., потому что он не повернулся ECHO OFF, потому что он занимался отладкой. Единственный другой возможный результат - ECHO is off., но только если он ранее установил команду @echo off.   -  person James K    schedule 31.10.2012


Ответы (5)


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%
person James K    schedule 20.10.2012
comment
как это обновить или удалить принтер, когда команда WMIC имеет значение GET? - person Lizz; 31.10.2012
comment
@Lizz - Это не так. Я специально отвечал на его вопрос хотел бы получить некоторые мысли о том, почему он, кажется, сбрасывает строку. Если то, что он говорит в самом начале своего вопроса, правда, удаление принтера будет простым делом добавления WMIC PRINTER WHERE "SERVERNAME LIKE '%PRINTERNAME%'" DELETE. - person James K; 31.10.2012
comment
Думаю, было больше одного вопроса. Спасибо за разъяснения :) - person Lizz; 31.10.2012
comment
WMIC PRINTER, WHERE SERVERNAME LIKE '% PRINTERNAME%' DELETE работает как шарм, и у меня уже есть сценарий, который делает это, конечная цель здесь - захватить значение принтера и временно сохранить его, затем я бы запустил удаление, но после этого я бы использовал что-то вроде RUNDLL32.exe PrintUI.DLL, PrintUIEntry / IN / cServername / n \\ Servername \ Printername, но проблема в том, что он сбрасывает значение, я немного исследовал после публикации этого, и один поток предположил, что это вывод команд в юникоде, а не в ASCII - person Matt Hamende; 05.11.2012

то, что вы ищете, это:

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 содержит имя, значение в качестве вывода, но вам нужно только значение, которое является вторым токеном.

кстати, поскольку мы больше не включаем пробел как отдельный, он должен работать даже с пробелами в значении. попробуйте.

person Nico    schedule 12.06.2013

Я обошелся с возвратом каретки 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 захватывает идентификатор объекта, который становится% 1, что удобно, если вы используете его для регистрации всех видов информации из WMI . Вам больше не нужно беспокоиться о возврате каретки Unicode.

Большим преимуществом этого подхода является то, что у вас есть умный командный файл, который преодолевает ограничения, которые дает вам wmic при использовании его внутри скрипта, и вы можете использовать его для чего угодно. вы можете использовать STDOUT командного файла в качестве параметра для чего-либо еще, даже в качестве входных данных для wmic!

person Nico van der Stok    schedule 21.09.2013
comment
Спасибо, но вы опоздали примерно на год, я закончил тем, что написал все это на vbscript, используя 2 объекта WMI в Win32_printers, и смог запросить нужные мне данные, а также позже автоматически перенести принтеры из одного UNC путь к новому пути, как часть функции, которую я выполнил для случая выбора для разных критериев, в целом я перенес около 60 000 объединенных сопоставлений принтеров UNC из моих журналов. - person Matt Hamende; 11.10.2013

Самый безопасный и общий вариант - вложить еще один цикл 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"

Проблема заключается в выводе Unicode команды wmic и плохом преобразовании в текст ANSI с помощью for /F, в результате чего остаются некоторые потерянные символы возврата каретки, что, в свою очередь, позволяет отображать некоторые дополнительные строки как непустые. Второй цикл for /F избавляется от этих артефактов преобразования.

Я также заменил параметр tokens=1 на delims=, чтобы не усекать возвращаемый элемент до первого пробела.

Также обратите внимание на следующие ответы пользователя dbenham:

person aschipfl    schedule 13.02.2017

person    schedule
comment
Добро пожаловать в Stack Overflow! Обычно рекомендуется включать какое-либо объяснение того, что делает код, когда вы включаете блок кода в ответ. - person Kevin Brown; 29.01.2015