Batch WMIC redirecting output and wrapping into va

2020-02-06 04:10发布

I'm trying to use WMIC to remove some old printers on our older print servers

if I use the below syntax from the command line it works

WMIC PRINTER WHERE "SERVERNAME LIKE '%%OLDSERVERNAME%%'" DELETE

I was asked to see if I could make it replace the printers or update them to spare the helpdesk from getting "how do I add my printer" calls

I tried some variation with SET to set the properties for SERVERNAME, it appear to process, but nothing changes and doing a GET shows the old value still.

so I figured I could do a FOR /F loop, wrap the name of the printer (sharename) in a variable and then use another command to recreate the printers, after the offending printers have been deleted.

here's my script

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

so you would think you'd get the value all wrapped up in a nice variable to do with as you wish but no, I turned echo on and it appears that the variable gets set back to null as soon as it's captured

my output looks like this...

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.

would love some thoughts on why it seems to be dumping the string.

Powershell and VBScript aren't out of the option either, I'm familar with both, just this seemed possible, and I really don't want to start over.

5条回答
Bombasti
2楼-- · 2020-02-06 04:34

WMIC is returning two lines, one with the printername, and one empty.
The solution to this is to test for empty lines.

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%
查看更多
我命由我不由天
3楼-- · 2020-02-06 04:39

what you are looking for is this:

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%

Explanation:

The unicode output of wmic includes a carriage return which is captured by the FOR /F which is what you do not want, as it means the 'enter' becomes part of your variable (%%A) and it also contains an empty line, which again will be outputted to %%A.

My example does the following: /format:cvs -- will output a comma seperated output so we can capture using the delimiter , skip=2 -- will skip the empty line at the beginning and skip the header row of the csv. tokens=2 -- the csv output contains the name,value as output, but you only want value, which is the second token.

by the way, because we no longer include space as a seperate it should even work with spaces in the value. give it a try.

查看更多
叛逆
4楼-- · 2020-02-06 04:48

The most secure and general variant is to nest another for /F loop, like this:

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"

The problem is the Unicode output of the wmic command and the poor conversion to ANSI text by for /F, which leaves some orphaned carriage-return characters, which in turn lets appear some additional lines as non-empty. The second for /F loop gets rid of these conversion artefacts.

I also replaced the tokens=1 option by delims= in order not to truncate the returned item at the first white-space.

Take also a look at the following related answers by user dbenham:

查看更多
劳资没心,怎么记你
5楼-- · 2020-02-06 04:51

I got around the UNICODE carriage return (which is really the problem here) like this:

@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

Save that as "wmi.bat" and execute your query like this:

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

My output looks like this:

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

You can imagine how you can play with this. the "%%B" portion puts all of the output of /VALUE (including spaces) into the %2 %%A captures the object id, which becomes %1 which is handy if you use this to log all sorts of information from WMI. You don't have to worry about the Unicode carriage return anymore.

The big advantage of this approach is that you have a clever batch file which overcomes the limitations that wmic gives you when using it inside a script, and you can use it for anything. you can use the STDOUT of the batch file as the parameter for anything else, even as input to wmic!

查看更多
Melony?
6楼-- · 2020-02-06 04:57
@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%
查看更多
登录 后发表回答