Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I get a list of all the .dll files in a folder, along with their version numbers?

-- DD

SpacerHey, Scripting Guy! AnswerScript Center

Hey, DD. You know, when we sit down to write this column we usually try to start off with an amusing and at least semi-relevant anecdote. In this case, that would mean a cute story about file versions. Unfortunately, none of the Scripting Guys could come up with an amusing anecdote about file versions; instead, the only things we could recall were nightmare scenarios involving mismatched, out-of-date, or incorrect .dll files. Talk about dredging up unpleasant memories: we didn’t think poor Dean would ever stop crying!

In other words, it’s safe to say that having a list of all the .dll files in a folder, along with the version number of each of those files, would be a pretty handy little thing to have. And what better way to retrieve that data than by using a script:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colFileList = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Windows\System32'} Where " _
        & "ResultClass = CIM_DataFile")

For Each objFile In colFileList
    If objFile.Extension = "dll" Then
        Wscript.Echo objFile.Name & " -- " & objFile.Version
    End If
Next

As you can see, we chose to tackle this problem by using a WMI script. Admittedly, we could have achieved the same results by using the FileSystemObject. We opted to go with WMI for one simple reason: that enables us to run this script against remote computers. (By contrast, the FileSystemObject pretty much limits us to working with the local computer.) Need to get file information off a remote computer named atl-fs-01? No problem; all you have to do is take the preceding script and change line 1 to look like this:

strComputer = "atl-fs-01"

And, yes, that’s exactly why we like WMI so much.

The script itself starts off by connecting to the WMI service on the local computer. We then run into this crazy-looking line of code:

Set colFileList = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Windows\System32'} Where " _
        & "ResultClass = CIM_DataFile")

It’s not pretty, but this is how you retrieve a collection of all the files in a specified folder (in this case, C:\Windows\System32). Basically what we’re saying here is this: “Bring me back all the CIM_DataFile objects associated with the directory named C:\Windows\System32.” Because CIM_Datafile is the WMI class that represents files, this query - crazy as it might look - simply brings back a collection of all the files found in C:\Windows\System32. What if you wanted a collection of all the files found in D:\Test? In that case you’d modify your query to look like this:

Set colFileList = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='D:\Test'} Where " _
        & "ResultClass = CIM_DataFile")

If you want to know more about Associators Of queries then check out the WMI SDK on MSDN. Alternatively, don’t worry too much about the nitty-gritty details; just remember that all you have to do is set Win32_Directory.Name to the name of the folder you want to work with.

From here on it’s a piece of cake. Once we have our collection we set up a For Each loop to walk us through each item (each file) in the collection. Inside that loop we use this line of code to check the value of the Extension property:

If objFile.Extension = "dll" Then

If Extension is equal to dll (note that this is just the three letters dll, without a dot; don’t include the dot when specifying the file extension in WMI) we then use this line of code to echo back the Name and Version:

Wscript.Echo objFile.Name & " -- " & objFile.Version

And what if the file extension isn’t equal to dll? No problem; in that case we just loop around and repeat the process with the next item in the collection.

When all is said and done we’ll get back information similar to this:

C:\Scripts>cscript dlls.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

c:\windows\system32\6to4svc.dll -- 5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)
c:\windows\system32\aaaamon.dll -- 5.1.2600.0 (xpclient.010817-1148)
c:\windows\system32\acctres.dll -- 6.00.2600.0000 (xpclient.010817-1148)
c:\windows\system32\acledit.dll -- 5.1.2600.0 (xpclient.010817-1148)
c:\windows\system32\aclui.dll -- 5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)
c:\windows\system32\activeds.dll -- 5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)

Believe it or not, that’s all it takes. (Boy, could we have used a script like this a few years ago!) Now, we should point out that this script - as requested - only retrieves information about the .dll files found in a single folder; the script does not check for .dll files in any subfolders of that folder. Could we modify the code and get the script to search all the subfolders of the target folder? Sure; as a starting point, take a look at this Hey, Scripting Guy! column, which shows you how to retrieve a list of all the files in a folder and its subfolders. All you need to do is take that script and look for the line of code that echoes back the file name:

Wscript.Echo objFile.Name

Modify that line to echo back the file name and the file version, and you’ll be in business:

Wscript.Echo objFile.Name & " -- " & objFile.Version

Got all that? Great. As for the Scripting Guys, we’re off to buy Dean an ice cream cone; we’re hoping that will cheer him up a bit. Poor little guy ….