Scripting Windows, part I: find oddities
24 02 2004I currently work for the NDR again. My job: Writing a handbook for the (Windows XP-based) notebooks (*yawn*), testing them (all systems are built from a standard client image) to make sure they comply with the specs (or whatever you want to call the document produced by guy from the company which was paid for writing it) and point out where the specs lack (*sigh*). And implement some of the features from the specs (actually, nobody told me officially to do so, but they’re glad if they have a bit less work and I just can’t write all day some boring handbook).
As the system is Windows based, most of the scripting (for login scripts etc.) is done in Batch. You know, that stuff interpreted by cmd.exe (formerly known as command.com).
With the command extensions (introduced with Windows NT 4.0, I think) using this interpreter has become a bit better than it was in DOS days. But if you’re used to Unix shells like Bash, it’s still a PITA. Why didn’t the guys I work for/with decide to equip the client image with a GNU layer like Cygwin when the decisions were made? I dunno, they loathe Linux by no means at all.
Scripting Windows is almost as bad as using it. Most of the system commands return no exit code (aka errorlevel) so you have to grep the output of an (often localized) app to do anything useful. Oh, right, there’s no grep under Windows. The traditional way is to use find which does a simple string comparison. If you need regular expressions, there is findstr. Whichever you use, it returns (and behaves like a good shell command) 0 if the string was found, else 1 (or some other positive integer value indicating an error).
One of the less good behaving programs is devcon; it refuses to return any useful error code. At least is it not localized, so you can grep… errr… find the output. That means as long as find does what it is supposed to do. Like when I had this code:
28: REM -- Enable/disable these device classes. 29: for %%i in (Infrared 1394 PCMCIA MTD TSDHD Modem) do ( 30: @echo Checking class =%%i... 31: REM -- Is there any device of this class? 32: devcon find "=%%i" | find /i /v "no match" 33: if %errorlevel% == 1 ( 34: REM --- Found something 35: call :dodev %cmd% "=%%i" 36: ) 37: @echo ... done 38: )
In line 32 devcon prints a list of devices or “No matching devices” if nothing was found, find looks for any line not containing the error string and returns a proper error level. That worked. For an hour or so. Until I changed some other part of the script. And suddenly find insisted on a return value of 0. Whatever devcon said.
First I though it was my fault and I accidently messed up that part of the code But after more than an hour of printf() debugging I was pretty sure that Windows was the real culprit. And what do you do if Windows starts to behave weird? Right, you reboot your machine.
And indeed, when Windows was up again exactly the same script worked fine again and find behaved as it should. Now, does that strengthen your trust in Windows Batch scripts?
I called this article “part I” as I have the bad feeling that I’ll encounter more weird Windows behaviour in the next few days…






Recent Comments