2

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.

Mohammad Arshad Alam
  • 9,694
  • 6
  • 38
  • 61
Matt Hamende
  • 139
  • 2
  • 4
  • 16
  • Putting your WMIC statement in the FOR loop is only giving %%A the value of the printer - it can't set it because your WMIC command is doing a GET, not a SET. Without the FOR loop, try doing the same WMIC command, but replace GET with SET. The core problem, though, is you want to update the print driver and name, which needs much more script than what you have here. – Lizz Oct 28 '12 at 05:52
  • @Lizz - Set, in this instance, is not a WMIC command, it is an internal command processor command to set an environmental variable. If you look at his output, you see 4 executed commands, where only two are expected. Specifically you see the variable `PRINTERNAME` set to **nameofprinter**, then set to nothing, then the command `ECHO` is called with no data, then you see the result of an empty `ECHO` command, which is "ECHO is on.", because he had not turned `ECHO OFF` because he was debugging. The only other possible result is `ECHO is off.`, but only if he had set `@echo off` command earlier. – James K Oct 31 '12 at 18:47

5 Answers5

5

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%
James K
  • 4,005
  • 4
  • 20
  • 28
  • how does this update or delete a printer when the WMIC command is GET? – Lizz Oct 31 '12 at 06:41
  • 1
    @Lizz - It does not. I was specifically responding to his question **"would love some thoughts on why it seems to be dumping the string."** If what he says at the very top of his question is true, deleting the printer would be a simple matter of adding `WMIC PRINTER WHERE "SERVERNAME LIKE '%PRINTERNAME%'" DELETE`. – James K Oct 31 '12 at 18:35
  • Guess there was more than one question. Thanks for the clarification :) – Lizz Oct 31 '12 at 18:44
  • 1
    WMIC PRINTER WHERE "SERVERNAME LIKE '%PRINTERNAME%'" DELETE" works like a charm and I already have a script that does this, the ultimate goal here is to capture the value of the printer and temporarily store it, then I would run the delete, but after, I would use something like "RUNDLL32.exe PrintUI.DLL,PrintUIEntry /IN /cServername /n\\Servername\Printername" but the problem is it's dumping the value, I researched a bit more after posting this, and one thread suggested that this command outputs in unicode as opposed to ASCII – Matt Hamende Nov 05 '12 at 16:38
1

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.

jeb
  • 78,592
  • 17
  • 171
  • 225
Nico
  • 11
  • 1
1

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!

  • Thanks but, you're about a year late, I ended up writing the whole thing in vbscript, leveraging 2 WMI objects in Win32_printers, and was able to query the data I needed, as well as later on auto-migrate printers from one UNC path to a new path, as part of a function that I ran through a select case for different criteria, all in all I migrated about 60,000 combined UNC printer mappings from my logs. – Matt Hamende Oct 11 '13 at 05:41
1

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:

aschipfl
  • 33,626
  • 12
  • 54
  • 99
0
@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%
Tom
  • 3,031
  • 1
  • 25
  • 33
js2010
  • 1
  • 1
    Welcome to Stack Overflow! Usually it's a good idea to include some kind of explanation of what the code does when you include a block of code in an answer. – Kevin Brown-Silva Jan 28 '15 at 21:29