Does anyone know of a script which essentially outputs a list of
machines on a network domain, with specific software installed.
For example, list all machines on the network domain with 'Google
Talk' installed, or 'Photoshop' etc.
I've been working on something but I can't get it to work accordingly.
Think I'm going down the wrong route all together!
Good luck and hope this helps.
' ***********************
' SoftwareSearch.vbs
' Vers 08/10/09
' by M. O'Neal @ BPA
' ***********************
'
' Search all systems in _Input.txt file for specific software.
On Error Resume Next ' Needed in any routine that uses the Err. object test
'******************************************************************************
' Program constants & variables
Public PROGRAM
PROGRAM = Left(WScript.ScriptName, Len(WScript.ScriptName)-4) ' Remove .vbs
extension
Public Const LogFormatted = True ' Set whether to log formatted messages
Public Const LogScreen = False ' Log to the screen instead of file, if True
Public Const LogNothing = 0 ' "log no messages" flag
Public Const LogNormal = 1 ' "log normal messages" flag
Public Const LogDebug = 2 ' "log normal & debug messages" flag
Public VerboseLevel ' Set to flag level above
' Any non-zero value causes logging
VerboseLevel = LogNormal ' Set the logging verbosity level
'******************************************************************************
' OFN constants
Public Const OFN_ALLOWMULTISELECT = &H200 ' multiple file selections;
use only with Open. OFN_EXPLORER must also be set.
Public Const OFN_CREATEPROMPT = &H2000 ' prompt to create a file
that doesn't exist. sets OFN_PATHMUSTEXIST. Works only with Open.
Public Const OFN_ENABLEHOOK = &H20 ' Enables the Hook function
specified in the lpfnHook member
Public Const OFN_ENABLETEMPLATE = &H40 ' Indicates that the
lpTemplateName member is a pointer to the name of a dialog box template
resource in the module identified by the hInstance member
Public Const OFN_EXPLORER = &H80000 ' Explorer-style dialog
boxes. Automatically set, but must specifically be set if
OFN_ALLOWMULTISELECT is used.
Public Const OFN_EXTENSIONDIFFERENT = &H400 ' On return, specifies that
the user typed a file name extension that differs from the extension
specified by lpstrDefExt. Not used if lpstrDefExt is unspecified.
Public Const OFN_FILEMUSTEXIST = &H1000 ' Accepts only existing file.
Works only with Open.
Public Const OFN_HIDEREADONLY = &H4 ' Hides the read-only box.
Should be set for Save As.
Public Const OFN_LONGNAMES = &H200000 ' Explorer-style dialog boxes
ignore this flag and always display long file names.
Public Const OFN_NOCHANGEDIR = &H8 ' Restores the current
directory to its original value if the user changed the directory while
searching for files.
Public Const OFN_NODEREFERENCELINKS = &H100000 ' Returns the path and file
name of the selected shortcut (.lnk) file. If not specified, the dialog box
returns the path and file name of the file referenced by the shortcut.
Public Const OFN_OVERWRITEPROMPT = &H2 ' In the Save As dialog box,
display a message box if the selected file already exists. The user must
confirm whether to overwrite the file.
Public Const OFN_PATHMUSTEXIST = &H800 ' Accepts only existing path.
Public Const OFN_READONLY = &H1 ' Selects the read-only check
box when the dialog box is created. Returns the state of the read-only check
box when the dialog box is closed. Only useful with Open.
Public Const OFN_TEST = &H600 ' NoNewFolder button ???
Public Const OFN_SHOWHELP = &H10 '
'******************************************************************************
' fso constants
Public Const FOR_READING = 1
Public Const FOR_WRITING = 2
Public Const FOR_APPENDING = 8
Public Const Create = True 'Create the file if it doesn't exist
Public Const NoCreate = False 'Don't create the file if it doesn't exist
Public Const OVERWRITE_EXISTING = True ' (vbTrue can't be used here)
Public objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
'******************************************************************************
' Set AppPath to the current drive & directory, otherwise Windows
' uses C:\WINNT\system32 (ugh!) as the current directory.
Public AppPath
AppPath = objFSO.GetParentFolderName(Wscript.ScriptFullName)
'******************************************************************************
'Definable parms
Public Const LogDir = ""
Public Const LogExt = "_log.txt" ' Log file extensions
Public Const inputExt = "_Input.txt" ' Input text data file
'******************************************************************************
' Registry constants
const HKEY_CLASSES_ROOT = &H80000000
const HKEY_CURRENT_USER = &H80000001
const HKEY_LOCAL_MACHINE = &H80000002
const HKEY_USERS = &H80000003
const HKEY_CURRENT_CONFIG = &H80000005
const REG_SZ = 1
const REG_EXPAND_SZ = 2
const REG_BINARY = 3
const REG_DWORD = 4
const REG_MULTI_SZ = 7
'******************************************************************************
'Use the vbscript "Dictionary" object as a collection
Set Software = CreateObject("Scripting.Dictionary")
Set Servers = CreateObject("Scripting.Dictionary")
CaseSensitive = vbFalse ' software names compare
' Create a program log
x = OpenLog( PROGRAM , objProgLog, FOR_WRITING)
If NOT x Then
WScript.Echo "Unable to create program log."
WScript.Sleep 5000
WScript.Quit(1)
End If
'------------------------------------------------------------------------------
'Read the server list file - Load the lists
'------------------------------------------------------------------------------
iFile = BrowseForFile(AppPath, "Input Files|*" & inputExt)
msg = "Reading input file: " & Program & inputExt
x = ProgLog(msg, LogNormal)
WScript.Echo msg
WScript.Echo "This might take a minute or two to complete."
Err.Clear
Set InputFile = OpenFile(iFile, FOR_READING, NoCreate)
If Err.Number<>0 Then
x = ProgLog(FormatErr(Err),LogNormal)
WScript.Quit(0) ' Set above will return err object
End If
Do Until InputFile.AtEndOfStream
x = GetLine(InputFile)
If x = "#" Then Exit Do
If x <> "" Then Software.Add x, x
Loop
Do Until InputFile.AtEndOfStream
x = UCase(GetLine(InputFile))
If x <> "" Then Servers.Add x, x
Loop
InputFile.Close
'------------------------------------------------------------------------------
' Create the CSV report file
'------------------------------------------------------------------------------
'Create a timestamp to make this file unique
TheTime = Now
strTime = PadTime(Year(TheTime)) & PadTime(Month(TheTime)) &
PadTime(Day(TheTime))
Err.Clear
ReportFilename = Append( Append(AppPath, LogDir), PROGRAM & "_" & strTime &
"_report.csv")
Set ReportFile = OpenFile(ReportFilename, FOR_WRITING, Create)
If Err.Number<>0 Then WScript.Quit(0) ' Set above will return err object
' Create the report file headding - the names of the software
ReportFile.WriteLine ", " & Join(Software.Keys, ",")
'------------------------------------------------------------------------------
'Loop on all Servers
'------------------------------------------------------------------------------
For Each strComputer in Servers
WScript.Echo strComputer
x = ProgLog("", LogNormal)
x = ProgLog(String(72, "-"), LogNormal)
x = ProgLog(strComputer, LogNormal)
x = ProgLog(String(72, "-"), LogNormal)
'------------------------------------------------------------------------------
'* Connect to WMI Service.
'------------------------------------------------------------------------------
Err.Clear
Set objWMIService =
GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer )
If Err.Number <> 0 Then ' trouble connection to strComputer's WMI
x = ProgLog(FormatErr(Err), LogNormal)
x = ProgLog("Unable to connect to WMI. WMI may not be properly installed
on " & strComputer, LogNormal)
Err.Clear
Else ' let's go get this node's info
' Reset software array items (software versions)
For Each strKey in Software.Keys
Software.Item(strkey) = "" ' *not installed*
Next
' Access the registry (using WMI)
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &
strComputer & _
"\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, InstalledSoftware
' Loop through all "Uninstallable" software
For Each strSubkey In InstalledSoftware
iRet = oReg.GetStringValue(HKEY_LOCAL_MACHINE, strKeyPath & strSubkey, _
"DisplayName", InstalledProgram)
If iRet<>0 Then
oReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath & strSubkey, _
"QuietDisplayName", InstalledProgram
End If
If InstalledProgram<>"" Then ' found a program
'WScript.Echo " " & InstalledProgram 'debug purposes
For Each ProgramToFind in Software
' Was this a program of interest?
If RegExTest(InstalledProgram, ProgramToFind, CaseSensitive) Then
oReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath & strSubkey, _
"DisplayVersion", Version
oReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath & strSubkey, _
"Publisher", Vendor
'Below is a different reporting style
'ReportFile.WriteLine strComputer & ", " & Vendor & ", " &
InstalledProgram & ", " & Version
x = ProgLog(" Found: " & Vendor & " - " & InstalledProgram & _
" - " & Version, LogNormal)
If Version="" OR IsNull(Version) Then Version="-unknown-"
Software.Item(ProgramToFind) = Version ' remember the version
for reporting
'Excel interprets 6.0 in a CSV as 6 - Perhaps preserve the 0
with period
End If ' program of interest
Next ' program to find in software
End If ' InstalledProgram<>""
Next ' Uninstallable software
' Report the software version information
ReportFile.WriteLine strComputer & ", " & Join(Software.Items, ",")
End If ' strComputer WMI connection test
Next ' End of strComputer loop on all servers
ReportFile.Close ' close the report file
x = ProgLog("", LogNormal)
x = ProgLog(String(72, "-"), LogNormal)
'------------------------------------------------------------------------------
x = CloseLog(objProgLog)
Set objFSO = Nothing
WScript.Echo "Done - Software information retrieved."
' Open the file up in notepad
Set objShell = CreateObject("Wscript.Shell")
'iErrorCode = objShell.Run("notepad.exe " & PROGRAM & LogExt,,False)
iErrorCode = objShell.Run(ReportFilename,,False)
'END of program
'||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'******************************************************************************
Function BrowseForFile(pstrPath, pstrFilter)
' OFN Dialog
Set objDialog = CreateObject("MSComDlg.CommonDialog")
objDialog.Filter = pstrFilter
objDialog.InitDir = pstrPath
objDialog.MaxFileSize = 256
objDialog.Flags = OFN_EXPLORER + OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR +
OFN_HIDEREADONLY
intResult = objDialog.ShowOpen()
BrowseForFile = objDialog.FileName
End Function
'******************************************************************************
Function PadTime(TheTime)
' Add a leading zero to times less than 10
If Len(TheTime) < 2 Then
PadTime = "0" & TheTime
Else
PadTime = TheTime
End If
End Function
'******************************************************************************
Function GetLine(objTextFile)
'******************************************************************************
'GetLine from objTextFile (and ignore any comments)
GetLine = "" ' sort-of-like "assume the worst" (return blank)
CommentStr = "'!" ' apostrophy and exclamation are comments
Do Until objTextFile.AtEndOfStream
L = Trim(objTextFile.Readline) 'Read a line (dissregard any leadding
spaces)
' Look for and skip any comment lines (based on leftmost character)
Chr1 = Left(L,1) 'Get the left most character of the line read from the
file
If InStr(CommentStr, Chr1)=0 Then ' it's comment free!
GetLine = L ' It ok to return this line to caller
Exit Function
End If
Loop ' Get another line
End Function
'******************************************************************************
Function Append(str1, str2)
'******************************************************************************
' Concatenate strings str1 and str2 with a single delimiter in between
' If they didn't specify a delimiter, assume backslash (future)
If Delim ="" then Delim ="\"
LD = Len(Delim)
'Test for delimiters
d1 = (Right(str1,LD) = Delim) ' Right most chr(s) of string 1 a delim?
d2 = (Left(str2,LD) = Delim) ' Left most chr(s) of string 2 a delim?
If d1 and d2 Then 'both have delims, remove one delimiter
Append = Left(str1, Len(str1)-LD) & str2
ElseIf NOT d1 and NOT d2 Then 'neither has a delim, add a delimiter
Append = str1 & Delim & str2
Else 'only one of them has a delimiter, so don't worry about it
Append = str1 & str2
End If
End Function
'******************************************************************************
Function RegExTest(SearchStr, pattern, CaseSensitive) 'as Logical
'******************************************************************************
' Returns TRUE if 'pattern' regular expression appears in 'SearchStr'
Dim regEx ' Create regEx object
Set regEx = New RegExp ' Make object a reg exp type
regEx.Pattern = pattern ' Set pattern
regEx.IgnoreCase = NOT(CaseSensitive)
RegExTest = regEx.Test(SearchStr) ' Execute the search test
str = "RegEx test for " & pattern & " in " & SearchStr & " = " &
RegExTest
If CaseSensitive Then str = "Case sensitive " & str
z = ProgLog(str, LogDebug)
End Function
'******************************************************************************
Function OpenFile(strMyFile, RW_Mode, CreateMode)
'******************************************************************************
On Error Resume Next ' Needed in any routine that uses the Err. object
test
If RW_Mode = FOR_READING Then
strMode = "reading"
ElseIf RW_Mode = FOR_WRITING Then
strMode = "writing"
ElseIf RW_Mode = FOR_APPENDING Then
strMode = "appending"
Else
strMode = "unknown r/w mode"
End If
Err.Clear
Set OpenFile = objFSO.OpenTextFile (strMyFile, RW_Mode, CreateMode)
If Err.Number<>0 Then
x = ProgLog("", LogNormal)
x = ProgLog("Could not open " & strMyFile & " for " & strMode , LogNormal)
'WScript.Echo "Could not open " & strMyFile & " for " & strMode
Else
x = ProgLog("", LogDebug)
x = ProgLog("Opened " & strMyFile & " for " & strMode, LogDebug)
End If
End Function
'******************************************************************************
' LOG FILE FUNCTIONS
'******************************************************************************
'******************************************************************************
Function OpenLog(strMyFile, objTextFile, Mode)
'******************************************************************************
'Create(if necessary) & open the specified log for writting or appending
On Error Resume Next ' Needed in any routine that uses the Err. object
test
OpenLog = vbFalse 'assume the worst
If LogScreen then 'they don't even want a log
OpenLog = vbTrue 'fake it and return
ElseIf VerboseLevel Then
If Mode=FOR_WRITING OR Mode=FOR_APPENDING Then
' Build the full path and filename
strFile = Append( Append(AppPath, LogDir), strMyFile & LogExt)
Err.Clear
Set objTextFile = objFSO.OpenTextFile (strFile, Mode, Create)
If Err.Number = 0 Then
objTextFile.WriteLine "<<< LOG OPENED AT " & Now & " >>>"
objTextFile.WriteBlankLines(1)
objTextFile.WriteLine "VerboseLevel = " & VerboseLevel
OpenLog = vbTrue
Else 'CreateLog didn't work - rats, how do we tell them
WScript.Echo "Unable to create log: " & strFile
End If
End If
End If
End Function
'******************************************************************************
Function CloseLog(objTextFile)
'******************************************************************************
If VerboseLevel AND Not(LogScreen) Then
objTextFile.WriteBlankLines(1)
objTextFile.WriteLine "<<< LOG CLOSED AT " & Now & " >>>"
objTextFile.WriteBlankLines(1)
objTextFile.Close
Set objTextFile = Nothing
End If
End Function
'******************************************************************************
Function ProgLog(msg, msgLevel)
'******************************************************************************
'Logs msg to the program log
On Error Resume Next ' Needed in any routine that uses the Err. object
test
If VerboseLevel => msgLevel Then
If LogFormatted Then
str = FormatMsg(msg)
Else
str = msg
End If
Err.Clear
If LogScreen Then
WScript.Echo str
Else
objProgLog.WriteLine str
End If
If Err.Number = 0 Then
ProgLog = vbTrue
Else
ProgLog = vbFalse
WScript.Echo "Unable to log message: " & msg
End If
End If
End Function
'******************************************************************************
Function FormatMsg(str)
'******************************************************************************
' Format message for logging and message box display
FormatMsg = " " & Now & " | " & str
End Function
'******************************************************************************
Function FormatErr(objErr)
'******************************************************************************
FormatErr = " ...Error 0x" & hex(objErr.Number) & " Source = " &
objErr.Source &_
vbCrLf & space(26) & " - " & objErr.Description
End Function
--
It''s my faults that keep me humble
'************************************************
' Software Search Input file
'************************************************
'-----------------------
' Software to search for
'-----------------------
ActivePerl
Adobe Reader
Java
MSXML
'Studio 2005 ' not installed
VC++
SourceSafe
Word Viewer
#
'-------------------
' Systems to search
'-------------------
Cons1 ' Terry
Cons2 ' Paul
Dis1.asr.site.com ' Sherry
Dis2.asr.site.com ' Done
Dis3.asr.site.com ' Mark
--
It''s my faults that keep me humble