Collect OS Information WA

Collect_Operating_System_Server_Information.WriteAction (WriteActionModuleType)

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityInternal
RunAsSystem.PrivilegedMonitoringAccount
InputTypeSystem.BaseData

Member Modules:

ID Module Type TypeId RunAs 
Script WriteAction Microsoft.Windows.ScriptWriteAction Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds

Source Code:

<WriteActionModuleType ID="Collect_Operating_System_Server_Information.WriteAction" Accessibility="Internal" RunAs="System!System.PrivilegedMonitoringAccount" Batching="false">
<Configuration>
<xsd:element name="TargetNetbiosComputer" type="xsd:string"/>
<xsd:element name="TimeoutSeconds" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptWriteAction">
<ScriptName>Collect_Operating_System_Server_Information.vbs</ScriptName>
<Arguments>$Config/TargetNetbiosComputer$</Arguments>
<ScriptBody><Script>
'Copyright (c) Microsoft Corporation. All rights reserved.
'*************************************************************************
' $ScriptName: "Common" $
'
' Purpose: To have one place for common stuff across various Exchange VBScripts
'
' $File: Common.vbs $
'*************************************************************************
' Option Explicit

SetLocale("en-us")

Dim EVENT_SOURCE
EVENT_SOURCE = "Exchange MOM"

'=============
'Event Type Constants
'=============
Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4

'=============
'Error Constants
'=============
Const ERROR_FILE_NOT_FOUND = -2147024894 'win32 error: 0x80070002

'=============
'Other Constants
'=============
Const MAX_LONG = 2147483647
Const MIN_LONG = -2147483648

'=============
'Initialize MOM Scripting Variables
'=============
Dim oAPI
Set oAPI = CreateObject("Mom.ScriptAPI")
If Err &lt;&gt; 0 Then
Wscript.Quit -1
End If

'=============
'Helper methods
'=============
' Method: CreateEvent
' Description: Logs Event
' Parameters: source, eventId, eventtype(error/warning/info/success), errormsg
'=============
Sub CreateEvent(lngEventID, lngEventType, strMsg)
Call oAPI.LogScriptEvent(EVENT_SOURCE, lngEventID, lngEventType, strMsg)
End Sub

'=============
' Method: HResultToString
' Description: Returns hresult value in string format 0x00000000(0)
' Parameters: hresult
'=============
Function HResultToString(hresult)
HResultToString = "0x" &amp; Hex(hresult) &amp; "(" &amp; hresult &amp; ")"
End Function

'=============
' Method: RegRead
' Description: Returns registry location value
' Parameters: strKey
'=============
Function RegRead(strKey)
On Error Resume Next
RegRead = "..."

Dim objShell
Set objShell = CreateObject("WScript.Shell")
RegRead = objShell.RegRead(strKey)
Set objShell = Nothing
End Function

'=============
' Method: ConvertDateTime
' Description: Returns datetime as formatted string
' Parameters: dtDateTime
'=============
Function ConvertDateTime(dtDateTime)
Dim objDate, objTime
objDate = DateSerial(Left(dtDateTime, 4), Mid(dtDateTime, 5, 2), Mid(dtDateTime, 7, 2))
objTime = TimeSerial(Mid(dtDateTime, 9, 2), Mid(dtDateTime, 11, 2), Mid(dtDateTime, 13, 2))

ConvertDateTime = FormatDateTime(objDate) &amp; " " &amp; FormatDateTime(objTime)
End Function

'=============
' Method: IsWMIRunning
' Description: Returns true/false
' Parameters: -
'=============
Function IsWMIRunning()
Dim objWMI

On Error Resume Next
Set objWMI = GetObject("winmgmts:root\cimv2")
If Err Then
IsWMIRunning = False
CreateEvent _
9013, _
EVENT_TYPE_ERROR, _
"The 'Windows Management Instrumentation' service (WinMgmt.exe) was not running when MOM tried to run a script that is dependent on this service. Check if the start up mode of this service is not set to 'disabled'."
Else
IsWMIRunning = True
End If

End Function

'=============
' Method: WMIExecQuery
' Description: Returns an object of type SWbemObjectSet
' Parameters:
' sNamespace - A WMI Namespace (ex. winmgmts:\\COMPUTERNAME\ROOT\cimv2).
' sQuery - A SQL Query (ex. SELECT * FROM Win32_OperatingSystem)
' iAlert - To echo/raise error
'=============
Function WMIExecQuery(sNamespace, sQuery, iAlert)
Dim oWMI, oQuery
Dim nErrNumber, sErrDescription
Dim nInstanceCount

On Error Resume Next
Set oWMI = GetObject(sNamespace)
On Error Goto 0

If IsEmpty(oWMI) And iAlert &lt;&gt; 0 Then
WScript.Echo "Unable to open WMI Namespace " &amp; sNamespace
Err.Raise 9100, "Unable to open WMI Namespace " &amp; sNamespace, "Check to see if the WMI service is enabled and running, and ensure this WMI namespace."
End If

On Error Resume Next
Set oQuery = oWMI.ExecQuery(sQuery)
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0

If (IsEmpty(oQuery) Or nErrNumber &lt;&gt; 0) And iAlert &lt;&gt; 0 Then
WScript.Echo "The Query '" &amp; sQuery &amp; "' returned an invalid result set. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
Err.Raise 9100, "The Query '" &amp; sQuery &amp; "' returned an invalid result set.", "Please check to see if this is a valid WMI Query. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oQuery.Count
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0

If nErrNumber &lt;&gt; 0 And iAlert &lt;&gt; 0 Then
WScript.Echo "The Query '" &amp; sQuery &amp; "' did not return any valid instances. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
Err.Raise 9100, "The Query '" &amp; sQuery &amp; "' did not return any valid instances.", "Please check to see if this is a valid WMI Query. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
End If

Set WMIExecQuery = oQuery
Set oQuery = Nothing
Set oWMI = Nothing
End Function

'=============
' Method: IsRunningAsSystem
' Description: Returns true/false
' Parameters: -
' Comments: If IsRunningAsSystem is False the caller should check if there is any error (If Err Then ...).
'=============
Function IsRunningAsSystem
Dim WshNetwork
Dim WMISystemAcct

IsRunningAsSystem = False

Set WshNetwork = CreateObject("WScript.Network")

' Use the well-known SID of the system account ("S-1-5-18") to get the correspondent object
Set WMISystemAcct = GetObject("WinMgmts:root/cimv2:Win32_SID='S-1-5-18'")

' WshNetwork.UserName gives the account running the current thread
' WMISystemAcct.AccountName gets the localized name of the system account

' No worries with string case in the comparsion below since, if the account is
' system, the name is extracted from the same location for both objects
If WshNetwork.UserName = WMISystemAcct.AccountName Then
IsRunningAsSystem = True
End If
End Function

'=============
'=============
'Exchange specific Helper methods
'=============
'=============

'=============
' Method: GetNamingContext
' Description: Returns propertyValue from rootDSE object
' Parameters: strPropertyName
'=============
Function GetNamingContext(strPropertyName)
GetNamingContext = ""

Dim IADsRootDSE
Set IADsRootDSE = GetObject("LDAP://rootDSE")

GetNamingContext = IADsRootDSE.Get(strPropertyName)
Set IADsRootDSE = Nothing
End Function

'=============
' Method: GetRootGC
' Description: Returns RootGC
' Parameters: -
'=============
Function GetRootGC()
Dim oGCCollection, oGC
Set oGCCollection = GetObject("GC:")
For each oGC in oGCCollection
Set GetRootGC = oGC
Next
End Function

'=============
' Method: GetCNValue
' Description: -
' Parameters: iOcurr, strData
'=============
Function GetCNValue(iOcurr, strData)
GetCNValue = GetTokValue(iOcurr, "CN=", ",", strData)
End Function

'=============
' Method: GetTokValue
' Description: -
' Parameters: iOcurr, strStartTok, strEndTok, strData
'=============
Function GetTokValue(iOcurr, strStartTok, strEndTok, strData)
Dim iIni, iEnd, iTokLen
iTokLen = Len(strStartTok)
iIni = 1
While iOcurr &gt; 0 ' Skip to the desired occurence
iIni = InStr(iIni, strData, strStartTok, vbTextCompare) + iTokLen
iOcurr = iOcurr - 1
WEnd
iEnd = InStr(iIni, strData, strEndTok, vbTextCompare)
GetTokValue = Mid(strData, iIni, (iEnd - iIni))
End Function

'=============
' Format Constants
'=============
Dim REC_DELIM, INFO_DELIM, IDENT
REC_DELIM = vbCr
INFO_DELIM = vbCr &amp; vbCr
IDENT = " "

'=============
' Method: OutputInfo
' Description: -
' Parameters: strValues, strProps, iPropsFrom, iLevel, blnHierarchical
' Remarks: Very similar to OutDiskInfo sub in Disk_Space_Problem.vbs
'=============
Function OutputInfo(strValues, strProps, iPropsFrom, iLevel, blnHierarchical)
Dim arrValues, arrProps, strLvl
Dim i

If strValues = "" Then Exit Function

On Error Resume Next
OutputInfo = ""
arrValues = Split(strValues, ";")
arrProps = Split(strProps, ",")

While iLevel &gt; 0
strLvl = strLvl &amp; IDENT
iLevel = iLevel - 1
WEnd

For i = iPropsFrom To UBound(arrProps)
OutputInfo = OutputInfo &amp; strLvl &amp; arrProps(i) &amp; ": " &amp; arrValues(i) &amp; REC_DELIM
If i = iPropsFrom and blnHierarchical Then strLvl = strLvl &amp; IDENT
Next
On Error GoTo 0
End Function


'Copyright (c) Microsoft Corporation. All rights reserved.
'*************************************************************************
' $ScriptName: "Collect Operating System Server Information" $
'
' Purpose - To collect information about the OS configuration of this machine which is
' relevant to its performance as an Exchange server
'
' $File: Collect_OS_Server_Information.vbs $
'*************************************************************************
SetLocale("en-us")

'Event ID Constants
EVENT_SOURCE = "Exchange MOM"
Const W2K_INFO_EVENT_ID = 9000
Const DISK_INFO_EVENT_ID = 9001
Const THREE_GB_ON_EVENT_ID = 9008
Const THREE_GB_OFF_EVENT_ID = 9009
Const UNEXPECTED_EXCEPTION_EVENT_ID = 9016

Const NOT_SET_STR = "&lt;not set&gt;"
Const WIN2KSERVER = "Microsoft Windows 2000 Server"

Const ONE_MEGA_IN_BYTES = 1048576
Const ONE_MEGA_IN_KBYTES = 1024
Const ONE_GIGA_IN_BYTES = 1073741824 ' Use an approximation instead of the actual GB = 1073741824
Const TWO_GIGA_IN_KBYTES = 2097024

Dim oArgs, TargetNetbiosComputer
Dim strOutput

Set oArgs = WScript.Arguments
if oArgs.Unnamed.Count &lt; 1 Then
Call WScript.Quit(-1)
end if

TargetNetbiosComputer = oArgs(0)

On Error Resume Next
If IsWMIRunning() Then
strOutput = "Computer and OS Information" &amp; INFO_DELIM
GetW2kInfoFromWMI TargetNetbiosComputer, strOutput
If Err Then
CreateEvent _
UNEXPECTED_EXCEPTION_EVENT_ID, _
EVENT_TYPE_ERROR, _
"An unhandled exception happened executing the response to event." &amp; REC_DELIM &amp; _
"Error source: " &amp; Err.Source &amp; REC_DELIM &amp; _
"Error description: " &amp; Err.Description &amp; REC_DELIM &amp; _
"Error number: " &amp; HResultToString(Err.Number)
End If
End If

' -- Subs -----------------------------------------------------------------------
Sub GetW2kInfoFromWMI(strComputer, strOutput)
Dim strWMIData, strFriendlyProps
Dim arrData, dblPhysMem

Dim strCPUData, strLastCPUData, iCPUTypeCountstrDriveData
Dim strPageFileData, strHotFixData

' Computer System
strWMIData = ""
strFriendlyProps = "System type,Manufacturer,Model,Number of processors,Physical memory (MBytes)"
GetWMIInfo "SystemType,Manufacturer,Model,NumberOfProcessors,TotalPhysicalMemory", "Select * from Win32_ComputerSystem", strWMIData, ";", REC_DELIM

arrData = Split(strWMIData, ";")
dblPhysMem = CDbl(arrData(4))

arrData(4) = FormatNumber(Round(arrData(4) / ONE_MEGA_IN_BYTES), 0)
strWMIData = Join(arrData, ";") &amp; REC_DELIM
strOutput = strOutput &amp; OutputInfo(strWMIData, strFriendlyProps, 0, 0, True)

' CPUs
strWMIData = ""
strFriendlyProps = "Name,Description,Clock speed (MHz),L2 Cache size (KBytes)"
GetWMIInfo "Name,Description,CurrentClockSpeed,L2CacheSize", "Select * from Win32_Processor", strWMIData, ";", REC_DELIM

strLastCPUData = ""
iCPUTypeCount = 0

For each strCPUData in Split(strWMIData, REC_DELIM)
If strCPUData = "" Then
Exit For
End If

If strLastCPUData = strCPUData Then
iCPUTypeCount = iCPUTypeCount + 1
Else
If iCPUTypeCount &gt; 0 Then
strOutput = strOutput &amp; iCPUTypeCount &amp; " x Processor(s):" &amp; REC_DELIM
strOutput = strOutput &amp; OutputInfo(strLastCPUData, strFriendlyProps, 0, 1, False)
strOutput = strOutput &amp; REC_DELIM
End If

iCPUTypeCount = 1
strLastCPUData = strCPUData
End If
Next

strOutput = strOutput &amp; iCPUTypeCount &amp; " x Processor(s):" &amp; REC_DELIM
strOutput = strOutput &amp; OutputInfo(strLastCPUData, strFriendlyProps, 0, 1, False)
strOutput = strOutput &amp; REC_DELIM

' Operating System
strWMIData = ""
strFriendlyProps = "MaxProcessMemorySize,Operating System,Build #,Service Pack,Build type,Installation date,Last boot time,Free physical memory (MBytes),Free virtual memory (MBytes)"
GetWMIInfo "MaxProcessMemorySize,Caption,BuildNumber,CSDVersion,BuildType,InstallDate,LastBootUpTime,FreePhysicalMemory,FreeVirtualMemory", "Select * from Win32_OperatingSystem", strWMIData, ";", REC_DELIM

arrData = Split(strWMIData, ";")
arrData(7) = FormatNumber(Round(arrData(7) / ONE_MEGA_IN_KBYTES), 0)
arrData(8) = FormatNumber(Round(arrData(8) / ONE_MEGA_IN_KBYTES), 0)
strWMIData = Join(arrData, ";") &amp; REC_DELIM

If CDbl(dblPhysMem) &gt;= CDbl(ONE_GIGA_IN_BYTES) Then
If arrData(2) &gt; 2195 Then
' Windows 2003
If CDbl(arrData(0)) = TWO_GIGA_IN_KBYTES Then
CreateEvent _
THREE_GB_OFF_EVENT_ID, _
EVENT_TYPE_WARNING, _
"The 3GB virtual address space option is not enabled on this computer." &amp; INFO_DELIM &amp; _
"It is strongly recommended to enable it and set the appropriate value for the USERVA option for all Exchange servers with more than 1 Gbyte " &amp; _
"of physical RAM that are running Windows Server 2003." &amp; INFO_DELIM &amp; _
"This server has " &amp; FormatNumber(Round(dblPhysMem / ONE_MEGA_IN_BYTES), 0) &amp; _
" Mbytes of physical RAM and is running " &amp; arrData(1) &amp; "."
End If
Else
' Windows 2000
If StrComp(arrData(1), WIN2KSERVER, vbTextCompare) &lt;&gt; 0 Then
If CDbl(arrData(0)) = TWO_GIGA_IN_KBYTES Then
CreateEvent _
THREE_GB_OFF_EVENT_ID, _
EVENT_TYPE_WARNING, _
"The 3GB virtual address space option is not enabled on this computer." &amp; INFO_DELIM &amp; _
"It is strongly recommended to enable this for all Exchange servers with more than 1 Gbyte " &amp; _
"of physical RAM and that are running Windows 2000 versions which support this feature." &amp; INFO_DELIM &amp; _
"This server has " &amp; FormatNumber(Round(dblPhysMem / ONE_MEGA_IN_BYTES), 0) &amp; _
" Mbytes of physical RAM and is running " &amp; arrData(1) &amp; "."
End If
End If
End If
Else
If CDbl(arrData(0)) &gt; TWO_GIGA_IN_KBYTES Then
CreateEvent _
THREE_GB_ON_EVENT_ID, _
EVENT_TYPE_WARNING, _
"The 3GB virtual address space option is enabled on this computer." &amp; INFO_DELIM &amp; _
"It is not recommended to enable this for any Exchange servers with less than 1 Gbyte " &amp; _
"of physical RAM." &amp; INFO_DELIM &amp; _
"This server has " &amp; FormatNumber(Round(dblPhysMem / ONE_MEGA_IN_BYTES), 0) &amp; _
" Mbytes of physical RAM and is running " &amp; arrData(1) &amp; "."
End If
End If

strOutput = strOutput &amp; OutputInfo(strWMIData, strFriendlyProps, 1, 0, True)

' Page files
strWMIData = ""
strFriendlyProps = "Page file,Initial size (MBytes),Maximum size (MBytes)"
GetWMIInfo "Name,InitialSize,MaximumSize", "Select * from Win32_PageFileSetting", strWMIData, ";", REC_DELIM

For each strPageFileData in Split(strWMIData, REC_DELIM)
If strPageFileData = "" Then
Exit For
End If

strOutput = strOutput &amp; OutputInfo(strPageFileData, strFriendlyProps, 0, 0, True) &amp; REC_DELIM
Next

' Hotfixes - slightly different treatment to remove duplicates QFEs
strFriendlyProps = "Hotfix,Description"

Dim dictQFE, objQFESet, objQFE

' Use a dictionary to prevent the same hotfix to be included more than one time in the event
Set dictQFE = CreateObject("Scripting.Dictionary")

' WMI return various bogus QFEs with ID equal to "File 1"
dictQFE.Add "File 1", Nothing
Set objQFESet = GetObject("WinMgmts:\\.\root\cimv2").InstancesOf("Win32_QuickFixEngineering")
For Each objQFE in objQFESet
If (Not dictQFE.Exists(objQFE.HotfixID)) Then
dictQFE.Add objQFE.HotfixID, Nothing
strOutput = strOutput &amp; OutputInfo(objQFE.HotfixID &amp; ";" &amp; objQFE.Description, strFriendlyProps, 0, 0, True) &amp; REC_DELIM
End If
Next

CreateEvent W2K_INFO_EVENT_ID, EVENT_TYPE_INFORMATION, strOutput
strOutput = ""

' Disks
strOutput = "Local Disks Information" &amp; INFO_DELIM
strWMIData = ""
strFriendlyProps = "Drive,File system,Size (MBytes),Free space (MBytes)"
GetWMIInfo "Name,FileSystem,Size,FreeSpace", "Select * from Win32_LogicalDisk where DriveType = 3", strWMIData, ";", REC_DELIM

For each strDriveData in Split(strWMIData, REC_DELIM)
If strDriveData = "" Then
Exit For
End If

arrData = Split(strDriveData, ";")
If arrData(3) &lt;&gt; NOT_SET_STR and arrData(2) &lt;&gt; NOT_SET_STR Then
arrData(3) = FormatNumber(Round(arrData(3) / ONE_MEGA_IN_BYTES), 0) &amp; " (" &amp; FormatNumber(100. * arrData(3) / arrData(2),2) &amp; "%)"
arrData(2) = FormatNumber(Round(arrData(2) / ONE_MEGA_IN_BYTES), 0)
strDriveData = Join(arrData, ";")
End If

strOutput = strOutput &amp; OutputInfo(strDriveData, strFriendlyProps, 0, 0, True) &amp; REC_DELIM
Next

CreateEvent DISK_INFO_EVENT_ID, EVENT_TYPE_INFORMATION, strOutput
strOutput = ""
End Sub

'--------------------------------------------------------------------------------------------
Sub GetWMIInfo(strProps, strWMIQuery, strRes, strFieldDelim, strRecordDelim)
Dim objWMISet, objWMI, strProp, objValue, strValue

Set objWMISet = WMIExecQuery("winmgmts:root\cimv2", strWMIQuery, 1)

For each objWMI in objWMISet

For each strProp in Split(strProps, ",")
objValue = objWMI.Properties_(strProp)

If not IsNull(objValue) Then
Select Case objWMI.Properties_(strProp).CIMType
Case 2,3,16,17,18,19,20,21 ' Integers
strValue = FormatNumber(objValue,0)
Case 4,5 ' Real number
strValue = FormatNumber(objValue,2)
Case 101 ' Date/time
strValue = ConvertDateTime(CStr(objValue))
Case Else
strValue = objValue
End Select
Else
strValue = NOT_SET_STR
End If

strRes = strRes &amp; strValue &amp; strFieldDelim
Next

strRes = Left(strRes, Len(strRes) - 1) &amp; strRecordDelim
Next
End Sub



</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="Script"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>