Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (03/06/09)
How Can I Select Domain Workstations with a WMI Filter?
Hey, Scripting Guy! Can you confirm that the below WMI filter will select domain workstations?
SELECT *
FROM Win32_ComputerSystem
WHERE strComputerRole = "Member Workstation"
- IB

Hi IB,
I can confirm that your command in fact will not work. The command should be written like this:
Select * from WIN32_computersystem where domainrole = 3
The WIN32_ComputerSystem WMI class is documented on MSDN. It is also talked about here on the Script Center. This “Hey, Scripting Guy!” article illustrates using the class.
How Can I Use copyFile, fileExists, and Increment a File Number?
Hey, Scripting Guy! How can I copy a file that always has the same name from one location to another, check whether the file exists, and if so rename it at the second location with a running number. In this way I could copy backup images to an external hard drive and have them “sorted” by name.
- SG

Hi SG,
Use the fileExists method to see if the file exists. Use the copyFile method to rename the file. Here is an interesting article that talks about creating file names based upon the date.
Here is a sample script that will illustrate some of the concepts we talked about: the fileExists method, the copyFile method, and incrementing a number:
Dim path,file, extension, originalFile
path = "C:\fso"
file = "a"
extension = ".txt"
originalFile = path & "\" & file & extension
copyPath = "C:\fso1"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(originalFile) Then
WScript.Echo "Original file exists. Proceeding to copy"
Else
WScript.Echo "Original file does not exist. Exiting script."
WScript.Quit
End If
If objFSO.FileExists(copyPath & "\" & file & extension) Then
WScript.Echo "copy file also exists. Incrementing name"
file = file & "1"
copyPath = copyPath & "\" & file & extension
objFSO.CopyFile originalFile, copyPath
Else
WScript.Echo "Copy file does not exist. Copying same"
copyPath = copyPath & "\" & file & extension
WScript.Echo copypath
WScript.Echo originalFile
objFSO.CopyFile originalFile, copyPath
End If
How Can I Have on Logon a Report of the Software Installed on a Client Computer?
Hey, Scripting Guy! How can I have a script that reports the software installed on a client machine at logon?
- TA

Hi TA,
This is one of the things that does not work really well. If a piece of software is installed using MSI, you can use the WIN32_Product WMI class and get a list easily. This WMI class is talked about in this article. Ultimately, the most reliable way to inventory installed software is to use the uninstall key from the registry:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
You will be interested in the following information:
| • |
DisplayName |
| • |
InstallDate |
| • |
Publisher |
| • |
Version |
If you have SMS installed on your computer, it creates a new WMI class based on the StdRegProv class that is called Win32Reg_AddRemovePrograms. It reads the registry key above, and displays the information. If not, you can use a script such as InventoryInstalledSoftwareRegKey.vbs that I just wrote especially for you:
'==========================================================================
'
'
' NAME: InventoryInstalledSoftwareRegKey.vbs
'
' AUTHOR: ed wilson, msft
' DATE : 1/22/2009
'
' COMMENT: Uses WMI to read the uninstall software registry key.
'
'==========================================================================
SubCheckCscript
Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\"&_
strComputer & "\root\default:StdRegProv")
strKeyPath = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
WScript.Echo "Subkeys under " _
& "HKEY_LOCAL_MACHINE\SYSTEM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
For Each subkey In arrSubKeys
WScript.Echo subkey
objReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath & "\" & subKey, "DisplayName", strDisplayName
objReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath & "\" & subKey, "Publisher", strPublisher
objReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath & "\" & subKey, "DisplayVersion", strDisplayVersion
If Not IsNull(strDisplayName) Then
WScript.Echo vbTab & "Display Name: " & strDisplayName
End If
If Not IsNull(strDisplayName) Then
WScript.Echo vbTab & "Publisher: " & strPublisher
End If
If Not IsNull(strDisplayName) Then
WScript.Echo vbTab & "Display Version: " & strDisplayVersion
End If
Next
Sub SubCheckCscript
If LCase(Right(Wscript.FullName, 11)) = "wscript.exe" Then
MsgBox "This script must be run under cscript.
Open the cmd prompt, type cscript
InventoryInstalledSoftwareRegKey.vbs"
WScript.Quit
End If
End Sub
‘---- end script
How Can I Find the Version of Several Executable Files Not Registered in the Registry?
Hey, Scripting Guy! Good morning. I need your help. I need to know the version of several executable files not registered in the registry. If I use the following lines in a .vbs script, I can obtain the version of a single executable, but I need to scan several directories (or all Drive C:\).:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Wscript.Echo objFSO.GetFileVersion("C:\... nameofexefile")
- UG

Hi UG,
You will need to recurse to do this. You script will look similar to this RecurseFolderListFileVersion.vbs script:
strTarget = "c:\fso"
Set objFSO = CreateObject("Scripting.FileSystemObject")
subRecursiveFolders objFSO.GetFolder(strTarget)
Sub subRecursiveFolders(Folder)
Set colFiles = Folder.files
For Each file In colFiles
WScript.Echo file.path
ver = objFSO.GetFileVersion(file.path)
If Len(ver) Then
WScript.Echo ver
Else
WScript.Echo "No version information available."
End If
Next 'for each file
For Each objFolder In Folder.subFolders
subRecursiveFolders objFolder
Next
End Sub
How Can I Use the Previous Script to Discover Only .Exe Files?
Hey, Scripting Guy! How can I use the above listed script to discover only .exe files?
- UG

Hi again UG,
You add this code to it:
intExt = InstrRev(file.path,".")
If Mid(file.path, intExt) = ".exe" Then
WScript.Echo file.path
End I
When you put it all together, it looks like the following script (because the extension is kept in a separate variable, it is easy to have it find only .dll or whatever types of files):
strTarget = "c:\fso"
fileExtension = ".exe"
Set objFSO = CreateObject("Scripting.FileSystemObject")
subRecursiveFolders objFSO.GetFolder(strTarget)
Sub subRecursiveFolders(Folder)
Set colFiles = Folder.files
For Each file In colFiles
intExt = InstrRev(file.path,".")
If Mid(file.path, intExt) = fileExtension Then
WScript.Echo file.path
ver = objFSO.GetFileVersion(file.path)
If Len(ver) Then
WScript.Echo ver
Else
WScript.Echo vbTab & "No version information available."
End If
End If
Next 'for each file
For Each objFolder In Folder.subFolders
subRecursiveFolders objFolder
Next
End Sub
Well, everyone, that is it for this edition of Quick-Hits Friday. It also draws another week to a close. We hope you have a save and enjoyable weekend (if you are on the other side of the world from us, you already have a head start on the weekend; good on ya mate!). Join us back here on Monday for another exciting week of “Hey, Scripting Guy!” articles. If you want to know what we will be talking about ahead of time, follow us on Twitter. Until Monday, be safe.
Ed Wilson and Craig Liebendorfer, Scripting Guys