Archive

Archive for the ‘Programming’ Category

Microsoft Scripting Stupidity

December 31st, 2008

The other day, I was tasked with writing a small maintenance script for work. The purpose of the script was to read a list of servers from a text file, go out to each of them, and perform certain operations on folders.

In order to do that, WMI had to be utilized, since that is the only way to perform actions on remote machines from a local workstation (or in this case, a task manager server).

In WMI, just like in most programming languages and frameworks, there are certain special characters that need to be escaped. For example, a simple quote character such as “, needs to be escaped because the compiler will interpret it as something else, such as the beginning or end of a text string. So, in PHP, for example, to assign this is my string to a variable, I would do:

$variable = "this is my string";

Notice how the string is enclosed in quotes. However, if I wanted to say something like And he said, “blah blah”, and then left, I would have to do it like this:

$variable2 = "And he said, \"blah blah\", and then left"; (Yes, in PHP, I could use single quotes to get around that limitation, but that’s not the point)

As you can see…the string had quotes in it, and they had to be preceded by a backslash so that they would not be interpreted as the end of the string. If I did not use them, and instead did:

$variable3 = "And he said, "blah blah", and then left";

the code would error out, because the first quote before blah would mean that I am done assigning my string to $variable3.

Ok…now that all the boring stuff is out of the way, back to VBScript and WMI. Let’s say that I wanted to delete a folder remotely and needed to write a script to do that, and let’s say that folder was C:\Documents and Settings\Luke, because for some reason, I wanted to break my remote machine by deleting my local profile. In WMI, and in almost everything else, a backslash “\”, is a special character, and must be escaped. In this case, any operation I would perform would need my ProfilePath variable to be C:\\Documents and Settings\\Luke.

So my code so far is:


Dim ProfilePath, server
ProfilePath = "C:\\Documents and Settings\\Luke"
server = myRemoteMachine.myDomain
Set serverWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & server & "\root\cimv2")
Set folder = serverWMIService.ExecQuery ("Select * From Win32_Directory Where Name = '" & ProfilePath & "'")

So far, I’ve basically asked WMI to go and grab me that folder, and it did, because I had the path properly escaped.

To delete stuff using WMI in the modern flavors of Windows, you can’t just say

folder.Delete

, as you could in Windows 2000, NT and the like. No…instead you have to get a big array, and enumerate every single file and folder inside every single folder. Basically, you have to prepare an entire directory tree, and work from the inside out.

This requires me to query WMI for the subfolders of that folder and the subfolders of that folder and so on.
We can do this pretty easily with another query like this: (note, I already have the objWMIService prepared and all that elsewhere in the script


Set colSubfolders = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & ProfilePath & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")

I ran that code (with all the other stuff I needed it to do), and it failed. Trying to find what failed took a few minutes since VBScript error reporting isn’t exactly perfect. End result was…it was failing on that query to get the subfolders. Through trial and error, I found that if I stripped the extra backslashes from ProfilePath…ie make it C:\Documents and Settings\Luke instead of C:\\Documents and Settings\\Luke, it would work.

Now wait a minute, wasn’t WMI just bitching at me at the beginning of my script that I had to escape the backslash because it was a special character?

All things considered, I have no idea why it chooses to work one way for some queries, and completely differently for others.

End result is: profilePath = Replace(profilePath,"\\","\") …and suck you very much VB

Programming, work