n part one of Comparing Computer Information, I covered some of WMI’s low-hanging fruit (meaning, information that is relatively easy to retrieve). However, there are other, rather interesting pieces of information that you may need to access, some of which might be just what you need to identify the problem with your misbehaving computer. Methods to access these pieces of information were not covered in the original code.
The code behind the new menu item is in the GetInstalledSoftwareData2 function. One of the curious things about this function is that instead of using the SWbemServices object already set as in the other methods, I set a new object using a root of “root/default:StdRegProv”. That is because the registry provider doesn’t fit into the standard WMI hierarchy under root/cimv2 namespace, so it exists in it’s own namespace. Using WMI (instead of using the Windows API functions to access the remote registry functions) has both advantages and disadvantages. The disadvantages are fairly obvious?the remote computer must have WMI installed, and using WMI is one more “layer” you have to deal with in your code. However, the advantages are real. The primary advantage is that WMI has a fairly consistent set of objects and object access methods, as well as a standard set of security methods, and this consistency is a useful thing while programming.
Using the registry allows you to get all the information about installed programs. However, since the programs were installed by multiple methods, the actual values that exist in the registry for a particular installation vary with the installation program. So, for getting the display name, you look first at “DisplayName” value, then the “QuietDisplayName”, and, finally, at the name of the key which is the root of these values. For the version, you look at the “DisplayVersion”, then the concatenation of “VersionMajor” and “VersionMinor”, or, finally, the “Version” value. For the installation location, look first at “InstallLocation”, and if that value isn’t present, look for the “UninstallString” value. This value is almost always located in the installation directory. At the very least, the installation directory will give you a hint as to where the program was installed.
Only add the entries where you found some non-blank entry for the display name. Note that by writing your own code, you gain quite a bit of flexibility in information retrieval, without too much extra pain (see Figure 2). For example, MSI installations will have the InstallatLocation values, and most pre-MSI installs will have the “UninstallString” value present (see Listing 1).Fixing the Inevitable
If you’ve worked extensively with Microsoft operating systems, you are familiar with Service Packs, and their smaller cousins, the Quick Engineering Fixes (QEF). Even with automatic notifications, it’s hard enough to keep up with all the current QEFs for your own local computer. Determining whether all the computers on your network have the correct QEFs installed is an even more daunting task.
WMI has an object that exposes the QEFs installed on a computer?Win32_QuickFixEngineering. However, this method has at least two problems that I’m aware of. First, on a pre-SP3 version of W2K, it can cause the WinMgmt process to hang. This bug is fixed in a post SP2 QEF, and in SP3 for W2K. Also, the WMI object seems to incorrectly parse some of the QEF information (which is located in the registry), and provides duplicate data for many of the QEFs. I have provided the WMI version of the program with the GetHotFixData function. For safety, I’ve written a private method GetOS that uses the public GetOsData to determine if you are running W2K and if you are at SP3 or above (see the code below). If you fail these two tests, the function returns False so you can abort the call to WMI (if you don’t abort the call, it might lock up the computer with 100% processor activity for WinMgmt).
Private Function GetOS_(ByVal xi_sWbemServices As SWbemServices) As VariantDim vntTmp As VariantDim vntRtn As VariantReDim vntRtn(1 To 2) As VariantvntTmp = GetOsData(xi_sWbemServices)If Left$(vntTmp(1, 13), 4) = “5.0.” Then If CLng(vntTmp(1, 25)) >= 3 Then vntRtn(1) = True vntRtn(2) = vbNullString Else vntRtn(1) = False vntRtn(2) = “If you are running W2K, _ you must have at least SP3 to run this ” & _ “method. You are running SP ” & vntTmp(1, 25) End IfElse vntRtn(1) = True vntRtn(2) = vbNullStringEnd IfGetOS = vntRtnEnd Function
I’ve also provided GetHotFixData2, which queries the registry directly (much as in the GetInstalledSoftwareData2). You can see the results in Figure 3. The code is very similar to the registry code for the installed software (download here).
The ways you can extend comparisons between two computers with WMI are extensive. I may revisit this program sometime in the future, but if you have any suggestions, please let me know.