Windows Server 2016 and above Discovery (Discovery)

Microsoft.Windows.Server.10.0.Discovery.DataSource (DataSourceModuleType)

This data source discovers Windows Server 2016 and above.

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsSystem.PrivilegedMonitoringAccount
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource Microsoft.Windows.Universal.Script.Discovery.DS Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval Seconds
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Server.10.0.Discovery.DataSource" RunAs="System!System.PrivilegedMonitoringAccount" Accessibility="Internal">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="IntervalSeconds" type="xsd:unsignedInt"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="TimeoutSeconds" type="xsd:unsignedInt"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="SourceId" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="VersionMask" type="xsd:string"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
<!--<OverrideableParameter ID="VersionMask" Selector="$Config/VersionMask$" ParameterType="string" />-->
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="Scheduler" TypeID="Microsoft.Windows.Universal.Script.Discovery.DS">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<cScriptName>Microsoft.Windows.Server.10.0.Discovery.Probe.vbs</cScriptName>
<cScriptParameters>"$Config/SourceId$" "$Target/Id$" "$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$" "$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$" "$Target/Property[Type="Windows!Microsoft.Windows.Server.Computer"]/IsVirtualNode$" "$Config/VersionMask$"</cScriptParameters>
<cScriptBody>
'Copyright (c) Microsoft Corporation. All rights reserved.

'*************************************************************************
' $ScriptName: "Microsoft.Windows.Server.Common"$
'
' Purpose: To have one place for common stuff across various BaseOS VBScripts
'
' $File: Microsoft.Windows.Server.Common.vbs$
'*************************************************************************

Option Explicit

SetLocale("en-us")

' LogScripEvent Constants
Const lsEventError = 1
Const lsEventWarning = 2
Const lsEventInformation = 3

' WMI Constants
Const wbemCimtypeUseDefault = 0 'Use Default Type CIM type - Custom
Const wbemCimtypeSint16 = 2 'Signed 16-bit integer
Const wbemCimtypeSint32 = 3 'Signed 32-bit integer
Const wbemCimtypeReal32 = 4 '32-bit real number
Const wbemCimtypeReal64 = 5 '64-bit real number
Const wbemCimtypeString = 8 'String
Const wbemCimtypeBoolean = 11 'Boolean value
Const wbemCimtypeObject = 13 'CIM object
Const wbemCimtypeSint8 = 16 'Signed 8-bit integer
Const wbemCimtypeUint8 = 17 'Unsigned 8-bit integer
Const wbemCimtypeUint16 = 18 'Unsigned 16-bit integer
Const wbemCimtypeUint32 = 19 'Unsigned 32-bit integer
Const wbemCimtypeSint64 = 20 'Signed 64-bit integer
Const wbemCimtypeUint64 = 21 'Unsigned 64-bit integer
Const wbemCimtypeDatetime = 101 'Date/time value
Const wbemCimtypeReference = 102 'Reference to a CIM object
Const wbemCimtypeChar16 = 103 '16-bit character

Const ErrAction_None = 0
Const ErrAction_Trace = 1
Const ErrAction_ThrowError = 16
Const ErrAction_Abort = 32
Const ErrAction_ThrowErrorAndAbort = 48

Const DISKSIZE_BYTES_IN_MB = 1048576

Dim g_ErrorEventNumber, g_TraceEventNumber, g_DebugFlag
g_ErrorEventNumber = 4001
g_TraceEventNumber = 4002
g_DebugFlag = False

'---------------------------------------------------------------------------
' Returns WMI Instance requested. Tries to execute WMI query a N times.
'---------------------------------------------------------------------------
Function WMIGetInstanceExTryN(oWMI, ByVal sInstance, ByVal N)
Dim oInstance, nInstanceCount
Dim e, i
Set e = New Error

For i = 0 To i &lt; N
On Error Resume Next
Set oInstance = oWMI.InstancesOf(sInstance)
e.Save
On Error Goto 0
If IsEmpty(oInstance) Or e.Number &lt;&gt; 0 Then
If i = N - 1 Then
ThrowScriptError "The class name '" &amp; sInstance &amp; "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If
Else
On Error Resume Next
nInstanceCount = oInstance.Count
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
If i = N - 1 Then
ThrowScriptError "The class name '" &amp; sInstance &amp; "' did not return any valid instances. Please check to see if this is a valid WMI class name.", e
End If
Else
Exit For
End If
End If
WScript.Sleep(1000)
Next

Set WMIGetInstanceExTryN = oInstance
End Function

'---------------------------------------------------------------------------
' Returns WMI Instance requested.
'---------------------------------------------------------------------------
Function WMIGetInstanceEx(oWMI, ByVal sInstance)
Dim oInstance, nInstanceCount
Dim e
Set e = New Error

On Error Resume Next
Set oInstance = oWMI.InstancesOf(sInstance)
e.Save
On Error Goto 0
If IsEmpty(oInstance) Or e.Number &lt;&gt; 0 Then
ThrowScriptError "The class name '" &amp; sInstance &amp; "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oInstance.Count
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
ThrowScriptError "The class name '" &amp; sInstance &amp; "' did not return any valid instances. Please check to see if this is a valid WMI class name.", e
End If

Set WMIGetInstanceEx = oInstance
End Function

'---------------------------------------------------------------------------
' Connect to WMI.
'---------------------------------------------------------------------------
Function WMIConnect(ByVal sNamespace)
Dim oWMI
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
ThrowScriptError "Unable to open WMI Namespace '" &amp; sNamespace &amp; "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
Set WMIConnect = oWMI
End Function

'---------------------------------------------------------------------------
' Returns WMI Instance requested.
'---------------------------------------------------------------------------
Function WMIGetInstance(ByVal sNamespace, ByVal sInstance)
Dim oWMI, oInstance
Set oWMI = WMIConnect(sNamespace)
Set oInstance = WMIGetInstanceEx(oWMI, sInstance)
Set WMIGetInstance = oInstance
End Function

'---------------------------------------------------------------------------
' Returns WMI Instance requested.
'---------------------------------------------------------------------------
Function WMIGetInstanceNoAbort(ByVal sNamespace, ByVal sInstance)
Dim oWMI, oInstance, nInstanceCount

On Error Resume Next
Set oWMI = GetObject(sNamespace)
If Not IsEmpty(oWMI) Then
Set oInstance = oWMI.InstancesOf(sInstance)
If Not IsEmpty(oInstance) And Err.Number = 0 Then
'Determine if we queried a valid WMI class - Count will return 0 or empty
nInstanceCount = oInstance.Count
If Err.Number = 0 Then
Set WMIGetInstanceNoAbort = oInstance
On Error Goto 0
Exit Function
End If
End If
End If

On Error Goto 0
Set WMIGetInstanceNoAbort = Nothing
End Function

'---------------------------------------------------------------------------
' Executes the WMI query and returns the result set.
'---------------------------------------------------------------------------
Function WMIExecQuery(ByVal sNamespace, ByVal sQuery)
Dim oWMI, oQuery, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
ThrowScriptError "Unable to open WMI Namespace '" &amp; sNamespace &amp; "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If

On Error Resume Next
Set oQuery = oWMI.ExecQuery(sQuery)
e.Save
On Error Goto 0
If IsEmpty(oQuery) Or e.Number &lt;&gt; 0 Then
ThrowScriptError "The Query '" &amp; sQuery &amp; "' returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oQuery.Count
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
ThrowScriptError "The Query '" &amp; sQuery &amp; "' did not return any valid instances. Please check to see if this is a valid WMI Query.", e
End If

Set WMIExecQuery = oQuery
End Function

'---------------------------------------------------------------------------
' Executes the WMI query and returns the result set, no abort version.
'---------------------------------------------------------------------------
Function WMIExecQueryNoAbort(ByVal sNamespace, ByVal sQuery)
Dim oWMI, oQuery
Set oWMI = GetObject(sNamespace)
Set oQuery = oWMI.ExecQuery(sQuery)
Set WMIExecQueryNoAbort = oQuery
End Function

'---------------------------------------------------------------------------
' Retrieves WMI property.
'---------------------------------------------------------------------------
Function GetWMIProperty(oWmi, sPropName, nCIMType, ErrAction)
Dim sValue, oWmiProp, oError
Set oError = New Error

' Check that object is valid.
If Not IsValidObject(oWmi) Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
ThrowScriptErrorNoAbort "Accessing property on invalid WMI object.", oError
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then _
Quit()

GetWMIProperty = ""
Exit Function
End If

' Get properties...
On Error Resume Next
Set oWmiProp = oWmi.Properties_.Item(sPropName)
oError.Save
If oError.Number &lt;&gt; 0 Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" &amp; sPropName &amp; "'.", oError
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then _
Quit()
End If
On Error Goto 0

If IsValidObject(oWmiProp) Then
sValue = oWmiProp.Value

If IsNull(sValue) Then ' If value is null, return blank to avoid any issues
GetWMIProperty = ""
Else
Select Case (oWmiProp.CIMType)
Case wbemCimtypeString, wbemCimtypeSint16, wbemCimtypeSint32, wbemCimtypeReal32, wbemCimtypeReal64, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16, wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64:
If Not oWmiProp.IsArray Then
GetWMIProperty = Trim(CStr(sValue))
Else
GetWMIProperty = Join(sValue, ", ")
End If
Case wbemCimtypeBoolean:
If sValue = 1 Or UCase(sValue) = "TRUE" Then
GetWMIProperty = "True"
Else
GetWMIProperty = "False"
End If
Case wbemCimtypeDatetime:
Dim sTmpStrDate

' First attempt to convert the whole wmi date string
sTmpStrDate = Mid(sValue, 5, 2) &amp; "/" &amp; _
Mid(sValue, 7, 2) &amp; "/" &amp; _
Left(sValue, 4) &amp; " " &amp; _
Mid (sValue, 9, 2) &amp; ":" &amp; _
Mid(sValue, 11, 2) &amp; ":" &amp; _
Mid(sValue, 13, 2)
If IsDate(sTmpStrDate) Then
GetWMIProperty = CDate(sTmpStrDate)
Else
' Second, attempt just to convert the YYYYMMDD
sTmpStrDate = Mid(sValue, 5, 2) &amp; "/" &amp; _
Mid(sValue, 7, 2) &amp; "/" &amp; _
Left(sValue, 4)
If IsDate(sTmpStrDate) Then
GetWMIProperty = CDate(sTmpStrDate)
Else
' Nothing works - return passed in string
GetWMIProperty = sValue
End If
End If
Case Else:
GetWMIProperty = ""
End Select
End If
Else
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" &amp; sPropName &amp; "'.", oError
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then _
Quit()

GetWMIProperty = ""
End If

If (ErrAction And ErrAction_Trace) = ErrAction_Trace Then _
WScript.Echo " + " &amp; sPropName &amp; " :: '" &amp; GetWMIProperty &amp; "'"
End Function

'---------------------------------------------------------------------------
' Class for error handling.
'---------------------------------------------------------------------------
Class Error
Private m_lNumber
Private m_sSource
Private m_sDescription
Private m_sHelpContext
Private m_sHelpFile
Public Sub Save()
m_lNumber = Err.number
m_sSource = Err.Source
m_sDescription = Err.Description
m_sHelpContext = Err.HelpContext
m_sHelpFile = Err.helpfile
End Sub
Public Sub Raise()
Err.Raise m_lNumber, m_sSource, m_sDescription, m_sHelpFile, m_sHelpContext
End Sub
Public Sub Clear()
m_lNumber = 0
m_sSource = ""
m_sDescription = ""
m_sHelpContext = ""
m_sHelpFile = ""
End Sub
Public Default Property Get Number()
Number = m_lNumber
End Property
Public Property Get Source()
Source = m_sSource
End Property
Public Property Get Description()
Description = m_sDescription
End Property
Public Property Get HelpContext()
HelpContext = m_sHelpContext
End Property
Public Property Get HelpFile()
HelpFile = m_sHelpFile
End Property
End Class

'---------------------------------------------------------------------------
' Creates an event and sends it back to the mom server.
'---------------------------------------------------------------------------
Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
' Retrieve the name of this (running) script
Dim FSO, ScriptFileName
Set FSO = CreateObject("Scripting.FileSystemObject")
ScriptFileName = FSO.GetFile(WScript.ScriptFullName).Name
Set FSO = Nothing

If Not IsNull(oErr) Then _
sMessage = sMessage &amp; ". " &amp; oErr.Description

On Error Resume Next
Dim oAPITemp
Set oAPITemp = CreateObject("MOM.ScriptAPI")
oAPITemp.LogScriptEvent ScriptFileName, g_ErrorEventNumber, lsEventError, sMessage
On Error Goto 0

WScript.Echo sMessage
End Function

'---------------------------------------------------------------------------
' Creates an event and sends it back to the mom server.
'---------------------------------------------------------------------------
Function ThrowScriptError(Byval sMessage, ByVal oErr)
On Error Resume Next
ThrowScriptErrorNoAbort sMessage, oErr
Quit()
End Function

'---------------------------------------------------------------------------
' Creates automation objects and returns it.
'---------------------------------------------------------------------------
Function MomCreateObject(ByVal sProgramId)
Dim oError
Set oError = New Error

On Error Resume Next
Set MomCreateObject = CreateObject(sProgramId)
oError.Save
On Error Goto 0

If oError.Number &lt;&gt; 0 Then
ThrowScriptError "Unable to create automation object '" &amp; sProgramId &amp; "'", oError
End If
End Function

'---------------------------------------------------------------------------
' Quits the script.
'---------------------------------------------------------------------------
Function Quit()
WScript.Quit()
End Function

'---------------------------------------------------------------------------
' Checks whether oObject is valid.
'---------------------------------------------------------------------------
Function IsValidObject(ByVal oObject)
IsValidObject = False
If IsObject(oObject) Then
If Not oObject Is Nothing Then
IsValidObject = True
End If
End If
End Function

'---------------------------------------------------------------------------
' Outputs arguments for debugging purposes
'---------------------------------------------------------------------------
Function TraceLogArguments
Dim oArgs
Set oArgs = WScript.Arguments
Dim i, sArgs
For i = 0 To oArgs.Count - 1
sArgs = sArgs &amp; " {" &amp; oArgs(i) &amp; "}"
Next
TraceLogMessage "Arguments:" &amp; sArgs
End Function

'---------------------------------------------------------------------------
' Verifies that number of arguments is correct
'---------------------------------------------------------------------------
Function VerifyNumberOfArguments(ByVal NumberOfArguments)
Dim oArgs
Set oArgs = WScript.Arguments
If oArgs.Count &lt;&gt; NumberOfArguments Then
Dim i, sArgs
For i = 0 To oArgs.Count - 1
sArgs = sArgs &amp; " {" &amp; oArgs(i) &amp; "}"
Next
ThrowScriptError "Invalid number of arguments (" &amp; oArgs.Count &amp; " instead of " &amp; NumberOfArguments &amp; "). Arguments:" &amp; sArgs, Null
End If
End Function

'---------------------------------------------------------------------------
' Outputs to file and echo for debugging purposes
'---------------------------------------------------------------------------
Function TraceLogMessage(ByVal sMessage)
WScript.Echo sMessage

If g_DebugFlag = True Then
' Retrieve the name of this (running) script
Dim FSO, ScriptFileName
Set FSO = CreateObject("Scripting.FileSystemObject")
ScriptFileName = FSO.GetFile(WScript.ScriptFullName).Name
Set FSO = Nothing

On Error Resume Next
Dim oAPITemp
Set oAPITemp = MOMCreateObject("MOM.ScriptAPI")
oAPITemp.LogScriptEvent ScriptFileName, g_TraceEventNumber, lsEventInformation, sMessage
On Error Goto 0
End If
End Function

'---------------------------------------------------------------------------
' Verifies the expression. If equals to False then generates an error and quits the script
' Usage:
' Verify Not WMISet Is Nothing, "WMISet is invalid!"
' Verify WMISet.Count = 1, "Invalid quantity of services with name 'Server' (qty = " &amp; WMISet.Count &amp; ")."
'---------------------------------------------------------------------------
Function Verify(ByVal bBool, ByVal sMessage)
If bBool = False Then
ThrowScriptError sMessage, Null
End If
End Function

Function GetRegistryKeyValue(ByVal keyPath, ByVal key)
Dim oReg, strKeyValue

strKeyValue = ""
GetRegistryKeyValue = strKeyValue
On Error Resume Next
Err.Clear
Set oReg = CreateObject("WScript.Shell")
If Err.Number &lt;&gt; 0 Then
Err.Clear
Exit Function
End If
strKeyValue = oReg.RegRead(keyPath &amp; key)
If Err.Number &lt;&gt; 0 Then
Err.Clear
Exit Function
End If

GetRegistryKeyValue = strKeyValue

' resume error
On Error Goto 0

End Function


'---------------------------------------------------------------------------
' Function: ExpressedInMB
' Usage:
' Parameter (SizeInBytes)
' Returns the Size Expressed in MBytes
'---------------------------------------------------------------------------
Function ExpressedInMB(byref SizeInBytes)
Dim NumberSizeExpInMB
NumberSizeExpInMB = Round(SizeInBytes / DISKSIZE_BYTES_IN_MB, 0)
ExpressedInMB = NumberSizeExpInMB
End Function

Private Function HasValue(Value)

Dim bNothing

bNothing = false

IF ( IsObject(Value) ) THEN
IF (Nothing is Value) THEN
bNothing = true
END IF
END IF

HasValue = Not ( IsEmpty(Value) or bNothing or IsNull(Value) )
End Function

Function GetServerOsVersionCheck(sComputerName,OsVersion,ByRef IsError)

On Error Resume Next

Err.Clear

Dim strQuery,oWmiSet, sWmiTarget, RegExp, ver, CountOWmi
IsError = False
GetServerOsVersionCheck = False

If ( IsObject(OsVersion)) Then
Exit Function
End If

sWmiTarget = "."

If ( Not IsObject(sComputerName)) Then
If (HasValue(sComputerName) and Len(sComputerName) &gt;0 ) Then
sWmiTarget = "" &amp; sComputerName
End If
End If

sWmiTarget = "winmgmts:\\" &amp; sWmiTarget &amp; "\root\cimv2"

StrQuery = "select Version from Win32_OperatingSystem where ProductType != 1"
Set oWmiSet = WMIExecQueryNoAbort(sWmiTarget, strQuery)
CountOWmi = oWmiSet.Count
If Err.Number = 0 Then
If CountOWmi &gt; 0 Then
IsError = False
Else
IsError = True
Exit Function
End If
Else
IsError = True
Exit Function
End If

Set RegExp = CreateObject("VBScript.RegExp")
RegExp.Pattern = OsVersion
If Err.Number &lt;&gt; 0 Then
IsError = True
Exit Function
End If

For each ver in oWmiSet
If (True = RegExp.Test(ver.Version)) Then
GetServerOsVersionCheck = True
Exit For
End If
Next

On Error Goto 0
End Function
'Copyright (c) Microsoft Corporation. All rights reserved.

' Parameters that should be passed to this script
' 0 MPElement ID
' 1 Target Id for ME this rule is running against
' 2 Computer (FQDN) that the OS will be hosted on
' 3 Computer ID (Key) that the OS will be hosted on
' 4 IsVirtualNode

Const Start_SnapShotDiscovery = 0
Const Exit_SnapShotDiscovery = 1
Const Exit_IncrementalDiscovery = 2

Call Main()

Sub Main()
On Error Resume Next

Dim oArgs
Dim SourceID, ManagedEntityId, TargetComputer, TargetComputerID, boolIsVirtualNode, VersionMask, iResult
Dim ArgCount
Dim oAPI, oDiscoveryData
Dim oError

Set oError = New Error

Err.Clear
Set oAPI = MOMCreateObject("MOM.ScriptAPI")
Set oArgs = WScript.Arguments
If (0 &lt;&gt; Err.Number) Then
oError.Save
ThrowScriptError "Cannot get script arguments.", oError
End If

ArgCount = oArgs.Count

If (ArgCount &lt; 4) Then
ThrowScriptError "Invalid number of arguments (" &amp; ArgCount &amp; " instead of 5." ,Null
End If

SourceID = oArgs(0)
ManagedEntityId = oArgs(1)
TargetComputer = oArgs(2)
TargetComputerID = oArgs(3)

If (ArgCount &gt;= 5) then
boolIsVirtualNode = oArgs(4)
Else
boolIsVirtualNode = False
End If


If (ArgCount &gt;= 6) then
VersionMask = oArgs(5)
Else
VersionMask = "10\."
End If


Err.Clear
Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceID, ManagedEntityId)
If (0 &lt;&gt; Err.Number) Then
ThrowScriptError "Cannot create discovery data object." ,Null
Quit()
End If

iResult = GetSnapshotDiscovery(VersionMask, boolIsVirtualNode)

If (Start_SnapShotDiscovery = iResult) Then
If ( False = DoDiscovery(TargetComputer, TargetComputerID, oDiscoveryData) ) Then
Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceID, ManagedEntityId)
oDiscoveryData.IsSnapShot = False
End If
Else
If (Exit_IncrementalDiscovery = iResult) Then
oDiscoveryData.IsSnapShot = False
End If
End If

Call oAPI.Return(oDiscoveryData)

End Sub


Function DoDiscovery(ByVal sTargetComputer, ByVal sTargetComputerID, ByVal oDisc)
Dim oInstanceComputer, oInstanceOperatingSystem, InstallationType, IsCore, CoreFull, WMIPowerSet, oPlan, PowerPlan
Dim computerClassId, OsClassId

DoDiscovery = False
On Error Resume Next
InstallationType = GetRegistryKeyValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "InstallationType")
computerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Full.Computer']$"
OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Full.OperatingSystem']$"
CoreFull = "Full"

If (InstallationType = "Server Core") Then
computerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Core.Computer']$"
OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Core.OperatingSystem']$"
CoreFull = "Core"
Else
If (InstallationType = "Nano Server") Then
computerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Nano.Computer']$"
OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Nano.OperatingSystem']$"
CoreFull = "Nano"
End If
End If

Err.Clear

Set oInstanceComputer = oDisc.CreateClassInstance(computerClassId)
Set oInstanceOperatingSystem = oDisc.CreateClassInstance(OsClassId)

If Err.Number &lt;&gt; 0 Then
Set oInstanceComputer = Nothing
Set oInstanceOperatingSystem = Nothing
Exit Function
End If


' Some group policies can restrict accessing to Win32_PowerPlan,
' need to handle it gracefully (for more information please see
' PS# 162496 in Server Management)

Set WMIPowerSet = WMIExecQueryNoAbort("winmgmts:\\" + sTargetComputer + "\root\cimv2\power", "select ElementName from Win32_PowerPlan where IsActive=true")
For Each oPlan In WMIPowerSet
PowerPlan = oPlan.ElementName
Next
If Err.Number &lt;&gt; 0 Then
PowerPlan = ""
Err.Clear
End If
Set WMIPowerSet = Nothing

With oInstanceComputer
.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sTargetComputerID
.AddProperty "$MPElement[Name='Microsoft.Windows.Server.10.0.Computer']/InstallType$", CoreFull
End With
With oInstanceOperatingSystem
.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sTargetComputerID
.AddProperty "$MPElement[Name='Microsoft.Windows.Server.10.0.OperatingSystem']/InstallType$", CoreFull
.AddProperty "$MPElement[Name='Microsoft.Windows.Server.10.0.OperatingSystem']/PowerPlan$", PowerPlan
End With

If Err.Number &lt;&gt; 0 Then
Exit Function
End If

Call oDisc.AddInstance(oInstanceComputer)
Call oDisc.AddInstance(oInstanceOperatingSystem)

If 0 = Err.Number Then
DoDiscovery = True
End If

On Error Goto 0

End Function

Function GetSnapshotDiscovery(OsVersion,IsVirtualNode)

Dim bIsOsValid,bIsError,iResult,bIsVirtualNode

On Error Resume Next
If (HasValue(IsVirtualNode)) Then
If (0 = Len(IsVirtualNode)) Then
IsVirtualNode = False
End If
Else
IsVirtualNode = False
End if

Err.Clear
bIsVirtualNode = CBool(IsVirtualNode)

If Err.Number &lt;&gt; 0 Then
GetSnapshotDiscovery = Exit_SnapShotDiscovery
On Error Goto 0
Exit Function
End If

If (True = bIsVirtualNode) Then
GetSnapshotDiscovery = Exit_SnapShotDiscovery
On Error Goto 0
Exit Function
End If

bIsOsValid = GetServerOsVersionCheck(".",OsVersion,bIsError)

If (bIsOsValid) Then
iResult = Start_SnapShotDiscovery
Else
If (bIsError) Then
iResult = Exit_IncrementalDiscovery
Else
iResult = Exit_SnapShotDiscovery
End IF

End If

GetSnapshotDiscovery = iResult
End Function
</cScriptBody>
<PsScriptName>Microsoft.Windows.Server.10.0.Discovery.Probe.ps1</PsScriptName>
<PowerShellScriptParameters>'$Config/SourceId$' '$Target/Id$' '$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$' '$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$' '$Target/Property[Type="Windows!Microsoft.Windows.Server.Computer"]/IsVirtualNode$' '$Config/VersionMask$'</PowerShellScriptParameters>
<PowerShellScriptParam>param($SourceId, $ManagedEntityId, $TargetComputer, $TargetComputerID, $boolIsVirtualNode, $VersionMask)</PowerShellScriptParam>
<PowerShellScriptBody>$ErrorActionPreference = "Stop"

# Event type constants
$EVENT_TYPE_LOG = 0
$EVENT_TYPE_ERROR = 1
$EVENT_TYPE_WARNING = 2
$EVENT_TYPE_INFORMATION = 4

# Typed property bag constants
$PROPERTY_TYPE_ALERT = 0
$PROPERTY_TYPE_EVENT = 1
$PROPERTY_TYPE_PERFORMANCE = 2
$PROPERTY_TYPE_STATE = 3

# State type constants
$STATE_SUCCESS = "Success"
$STATE_WARNING = "Warning"
$STATE_ERROR = "Error"

$WMI_Partition_To_LogicalDisk = "Win32_LogicalDiskToPartition"
$WMI_Drive_To_Partition = "Win32_DiskDriveToDiskPartition"
$WMI_DISk_To_Partition = "Win32_DiskDriveToDiskPartition"

$momAPI = new-object -comObject MOM.ScriptAPI
if ($null -eq $momAPI)
{
exit
}

Function Load-CimModules
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
}
}

Load-CimModules

# WMI Constant
$wbemCimtypeUseDefault = 0 #Use Default Type CIM type - Custom
$wbemCimtypeSint16 = 2 #Signed 16-bit integer
$wbemCimtypeSint32 = 3 #Signed 32-bit integer
$wbemCimtypeReal32 = 4 #32-bit real number
$wbemCimtypeReal64 = 5 #64-bit real number
$wbemCimtypeString = 8 #String
$wbemCimtypeBoolean = 11 #Boolean value
$wbemCimtypeObject = 13 #CIM object
$wbemCimtypeSint8 = 16 #Signed 8-bit integer
$wbemCimtypeUint8 = 17 #Unsigned 8-bit integer
$wbemCimtypeUint16 = 18 #Unsigned 16-bit integer
$wbemCimtypeUint32 = 19 #Unsigned 32-bit integer
$wbemCimtypeSint64 = 20 #Signed 64-bit integer
$wbemCimtypeUint64 = 21 #Unsigned 64-bit integer
$wbemCimtypeDatetime = 101 #Date/time value
$wbemCimtypeReference = 102 #Reference to a CIM object
$wbemCimtypeChar16 = 103 #16-bit character

$ErrAction_None = 0
$ErrAction_Trace = 1
$ErrAction_ThrowError = 16
$ErrAction_Abort = 32
$ErrAction_ThrowErrorAndAbort = 48

$DISKSIZE_BYTES_IN_MB = 1048576
$DriveLetterMaxSize = 3

$g_ErrorEventNumber = 4001
$g_TraceEventNumber = 4002
$g_DebugFlag = $false

#---------------------------------------------------------------------------
# Returns WMI Instance requested. Tries to execute WMI query a N times.
#---------------------------------------------------------------------------
Function WMIGetInstanceExTryN
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery,
[int]$N)

for ($i = 0; $i -lt $N; $i++)
{
$error.Clear();

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
catch
{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if ($error.Count -gt 0)
{
if ($i -eq ($N-1))
{
ThrowScriptError ("The class name '" + $sInstanceQuery + "' returned no instances. Please check to see if this is a valid WMI class name.") $error[0]
}
}
else
{
break;
}
sleep -m 1000
}

return $oInstance
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstanceEx
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)

$error.Clear();

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
catch
{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if ($error.Count -gt 0)
{
ThrowScriptError ("The class name '" + $sInstanceQuery + "' returned no instances. Please check to see if this is a valid WMI class name.") $error[0]
}

return $oInstance
}

#---------------------------------------------------------------------------
# Connect to WMI.
#---------------------------------------------------------------------------
Function WMIConnect
{
param ([string]$sTargetComputer,
[string]$sNamespace)

$error.Clear()

# !!! Refactoring comment:
# Original VBScript only tries to connect to the namespace. Piping to get only the first one saves time.
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oWMI = Get-CimClass -CimSession $cimsession -Namespace $sNamespace -ErrorAction SilentlyContinue | select -First 1
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if ($error.Count -gt 0)
{
$msg = "Unable to open WMI Namespace 'winmgmts:\\" + $sTargetComputer + "\" + $sNamespace + "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists."
ThrowScriptError $msg $error[0]
}
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstance
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)

WMIConnect $sTargetComputer $sNamespace
$oInstance = WMIGetInstanceEx $sTargetComputer $sNamespace $sInstanceQuery
return $oInstance
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstanceNoAbort
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)


Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
catch
{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

return $oInstance
}

#---------------------------------------------------------------------------
# Executes the WMI query and returns the result set.
#---------------------------------------------------------------------------
Function WMIExecQuery
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sQuery)

$error.Clear()

# !!! Refactoring comment:
# Original VBScript only tries to connect to the namespace. Piping to get only the first one saves time.
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oWMI = Get-CimClass -CimSession $cimsession -Namespace $sNamespace -ErrorAction SilentlyContinue | select -First 1
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -gt 0)
{
$msg = "Unable to open WMI Namespace 'winmgmts:\\" + $sTargetComputer + "\" + $sNamespace + "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists."
ThrowScriptError $msg, $error[0]
}


Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oQuery = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}
catch
{
$oQuery = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if ($error.Count -gt 0)
{
ThrowScriptError ("The Query '" + $sQuery + "' returned an invalid result set. Please check to see if this is a valid WMI Query.") $error[0]
}

return $oQuery
}

#---------------------------------------------------------------------------
# Executes the WMI query and returns the result set, no abort version.
#---------------------------------------------------------------------------
Function WMIExecQueryNoAbort
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sQuery)

$ErrorActionPreference = "SilentlyContinue"

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $sTargetComputer -SessionOption $cimSessionOption
$oQuery = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}
catch
{
$oQuery = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

return $oQuery
}

#---------------------------------------------------------------------------
# Creates an event and sends it back to the mom server.
#---------------------------------------------------------------------------
Function ThrowScriptErrorNoAbort
{
param ([string]$sMessage,
[System.Management.Automation.ErrorRecord]$oErr)
# Retrieve the name of this (running) script
$ScriptFileName = $MyInvocation.ScriptName

if ($oErr -ne $null)
{
$sMessage = $sMessage + ". " + $oErr.ErrorDetails
}

$momAPI.LogScriptEvent($ScriptFileName, $g_ErrorEventNumber, $EVENT_TYPE_ERROR, $sMessage)

Write-Host $sMessage
}

#---------------------------------------------------------------------------
# Creates an event and sends it back to the mom server.
#---------------------------------------------------------------------------
Function ThrowScriptError
{
param ([string]$sMessage,
[System.Management.Automation.ErrorRecord]$oErr)
ThrowScriptErrorNoAbort $sMessage $oErr
exit
}

#---------------------------------------------------------------------------
# Outputs to file and echo for debugging purposes
#---------------------------------------------------------------------------
Function TraceLogMessage
{
param ([string]$sMessage)

Write-Host $sMessage

If ($g_DebugFlag -eq $true)
{
# Retrieve the name of this (running) script
$ScriptFileName = $MyInvocation.ScriptName

$momAPI.LogScriptEvent($ScriptFileName, $g_TraceEventNumber, $EVENT_TYPE_INFORMATION, $sMessage)
}
}

#---------------------------------------------------------------------------
# Verifies the expression. If equals to False then generates an error and quits the script
# Usage:
# Verify Not WMISet Is Nothing, "WMISet is invalid!"
# Verify WMISet.Count = 1, "Invalid quantity of services with name 'Server' (qty = " &amp; WMISet.Count &amp; ")."
#---------------------------------------------------------------------------
Function Verify
{
param ([bool]$bBool,
[string]$sMessage)

If ($bBool -eq $false)
{
ThrowScriptError $sMessage $null
}
}

Function GetRegistryKeyValue
{
param ([string]$keyPath,
[string]$key)

$error.Clear()

$strKeyValue = Get-ItemProperty -Path $keyPath -Name $key -ErrorAction SilentlyContinue
if ($error.Count -gt 0)
{
ThrowScriptError ("An error occurred while reading the registry: '" + $keyPath + $key + "'") $error[0]
}
return $strKeyValue.$key
}


#---------------------------------------------------------------------------
# Function: ExpressedInMB
# Usage:
# Parameter (SizeInBytes)
# Returns the Size Expressed in MBytes
#---------------------------------------------------------------------------
Function ExpressedInMB
{
param ($SizeInBytes)

$NumberSizeExpInMB = [math]::Round($SizeInBytes / $DISKSIZE_BYTES_IN_MB, 0)
return $NumberSizeExpInMB
}

Function CheckCluster
{
param ([string]$sTargetComputer)

$error.Clear()
$oInstances = WMIExecQueryNoAbort $sTargetComputer "root\cimv2" "Select ID, Name from Win32_ServerFeature where Name = 'Failover Clustering'"

if ($error.Count -gt 0 -or $oInstances.Count -eq 0)
{
return $false
}
else
{
$ClusterName = (Get-ItemProperty -Path "HKLM:\Cluster" -Name "ClusterName" -ErrorAction SilentlyContinue ).ClusterName
return -Not [string]::IsNullOrEmpty($ClusterName)
}
}

Function CheckIsClusterDisk
{
param ([string]$sDeviceID, [string]$sSerialNumber, [bool]$IsCluster, [hashtable]$ClusterVolumes)


$bFlag = $false

if ($IsCluster -eq $false -or [string]::IsNullOrEmpty($sSerialNumber) )
{
return $bFlag
}

$SerialNumber = $sSerialNumber.TrimStart("0")
$DiskId = $SerialNumber + $sDeviceID
$VolId = $ClusterVolumes[$DiskId]

$bFlag = $VolId -ne $null

return $bFlag

}

Function GetClusterDiskCollection
{
param ([string]$sTargetComputer)

$Volumes = @{}
$error.Clear()
$oInstances = WMIExecQueryNoAbort $sTargetComputer "root\MSCluster" "Select Path, SerialNumber From MSCluster_DiskPartition"

if ($error.Count -eq 0)
{
foreach ($item in $oInstances)
{
$hexsn = "{0:X}" -f $item.SerialNumber
$Path = $item.Path
$VolId = $hexsn + $Path

if ([string]::IsNullOrEmpty($VolId))
{
continue
}

$Volumes[$VolId] = $VolId

}
}

return $Volumes
}

#---------------------------------------------------------------------------
# Function: SwitchBoolean
# Usage:
# Parameter (bIn)
# Returns a Boolean
#---------------------------------------------------------------------------
Function SwitchBoolean([string]$bIn)
{
if ($bIn.ToLower() -eq "false")
{
return "true"
}
else
{
return "false"
}
}

Function Is_NanoServer
{
$ErrorActionPreference="SilentlyContinue"
$error.Clear()
$IsNano = (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels").GetValue("NanoServer")
$error.Clear()
$IsNano = $IsNano -eq 1

return $IsNano

}

Function GetPerfmonInstance($sName)
{
$sName = $sName -replace("\(","[")
$sName = $sName -replace("\)","]")
$sName = $sName -replace("/","_")
$sName = $sName -replace("#","_")

return $sName
}

Function Convert-ToBoolean([string] $sBool)
{
[bool] $result = $false
[bool] $iresult = $false

if ($false -eq [string]::IsNullOrEmpty($sBool) )
{
$result = $sBool.Equals("true",[System.StringComparison]::InvariantCultureIgnoreCase)
$iresult = $sBool.Equals("1",[System.StringComparison]::InvariantCultureIgnoreCase)
$result = $result -or $iresult
}

return $result
}

Function Get-StringProperty([string]$Property,[int]$MaxSize = 256)
{
if ([string]::IsNullOrEmpty($Property))
{
return [string]::Empty
}

if ($Property.Length -gt $MaxSize)
{
return $Property.Substring(0,$MaxSize)
}

return $Property
}

Function Load-Module ([string] $ModuleName)
{
if ([string]::IsNullOrEmpty($ModuleName) )
{
return $false
}

$ErrorActionPreference="SilentlyContinue"
$error.Clear()

$retval = $false
$cim = Get-Module -Name $ModuleName

########Check for powershell 1.0
if ($error.Count -ne 0)
{
$type = $error[0].Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
$error.Clear()
return $retval
}

$error.Clear()
}

if ($null -eq $cim)
{
Import-Module $ModuleName
if ($error.Count -eq 0)
{
$retval = $true
}

$error.Clear()
}
else
{
$retval = $true
}

return $retval


}

Function Unload-Module([string]$ModuleName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

if ([string]::IsNullOrEmpty($ModuleName))
{
return
}

$module = Get-Module $ModuleName
if ($null -eq $module)
{
return
}

Remove-Module -Name $ModuleName -Force
}


Function Load-CimModules
{
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()
}
}#Copyright (c) Microsoft Corporation. All rights reserved.

# Parameters that should be passed to this script
# 0 MPElement ID
# 1 Target Id for ME this rule is running against
# 2 Computer (FQDN) that the OS will be hosted on
# 3 Computer ID (Key) that the OS will be hosted on
# 4 IsVirtualNode

$Start_SnapShotDiscovery = 0
$Exit_SnapShotDiscovery = 1
$Exit_IncrementalDiscovery = 2

Function Main()
{

$result = Init-ScomHelper

if ($false -eq $result)
{
return
}

$oDiscoveryData = Get-DiscoveryData

if ($null -eq $oDiscoveryData)
{
return
}

$ErrorActionPreference = "SilentlyContinue"

$SerializeDiscoveryData = [Scom.Helper.ConvertData]::GetDataItemFromOutput($oDiscoveryData)
Write-Host "$SerializeDiscoveryData"
}

Function Load-CimModules
{
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()
}
}

Function DoDiscovery
{
param ([string]$sTargetComputer, [string]$sTargetComputerID, $oDisc)

$ErrorActionPreference = "SilentlyContinue"
$result = $false

$CoreFull = "Full"
$ComputerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Full.Computer']$"
$OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Full.OperatingSystem']$"
$InstallationType = GetRegistryKeyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" "InstallationType"

if ($InstallationType -eq "Server Core")
{
$CoreFull = "Core"
$ComputerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Core.Computer']$"
$OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Core.OperatingSystem']$"
}
elseif($InstallationType -eq "Nano Server")
{
$CoreFull = "Nano"
$ComputerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Nano.Computer']$"
$OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Nano.OperatingSystem']$"
}

$Error.Clear()

$oInstanceComputer = $oDisc.CreateClassInstance($ComputerClassId)
$oInstanceOperatingSystem = $oDisc.CreateClassInstance($OsClassId)
if (0 -ne $Error.Count)
{
return $result
}

$PowerPlan = Get-PowerPlan
$Error.Clear()


$oInstanceComputer.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sTargetComputerID)
$oInstanceComputer.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Computer']/InstallType$", $CoreFull)
$oInstanceOperatingSystem.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sTargetComputerID)
$oInstanceOperatingSystem.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.OperatingSystem']/InstallType$", $CoreFull)
$oInstanceOperatingSystem.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.OperatingSystem']/PowerPlan$", $PowerPlan)

if (0 -ne $Error.Count)
{
return $result
}


$oDisc.AddInstance($oInstanceComputer)
$oDisc.AddInstance($oInstanceOperatingSystem)

$result = 0 -eq $Error.Count

return $result

}

Function Get-SnapshotDiscovery($OsVersion,$IsVirtualNode)
{
$ErrorActionPreference = "SilentlyContinue"

$bIsVirtualNode = Convert-ToBoolean -sBool $IsVirtualNode

if ($bIsVirtualNode)
{
return $Exit_SnapShotDiscovery
}

$Filter = "ProductType != 1"
$Error.Clear()

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$result = Get-CimInstance -CimSession $cimsession -ClassName "Win32_OperatingSystem" -Filter $Filter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if(0 -ne $Error.Count)
{
$Error.Clear()
$result = Get-WmiObject -Class "Win32_OperatingSystem" -Filter $Filter

if (0 -ne $Error.Count)
{
return $Exit_IncrementalDiscovery
}

}

if([string]::IsNullOrEmpty($OsVersion))
{
$OsVersion = "10\."
}

if ($null -eq $result -or -not ($result.Version -match $OsVersion))
{
$result = $Exit_SnapShotDiscovery
}
else
{
$result = $Start_SnapShotDiscovery
}

return $result
}

Function Get-DiscoveryData
{
$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
$oDiscoveryData = $momAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
if (0 -ne $Error.Count)
{
return $null
}

$discoveryType = Get-SnapshotDiscovery -OsVersion $VersionMask -IsVirtualNode $boolIsVirtualNode

If ($Start_SnapShotDiscovery -eq $discoveryType)
{
$result = DoDiscovery $TargetComputer $TargetComputerID $oDiscoveryData
if ($false -eq $result)
{
$Error.Clear()
$oDiscoveryData = $momAPI.CreateDiscoveryData(0, $SourceID, $ManagedEntityId)
$oDiscoveryData.IsSnapshot = $false
}
}
else
{
if ($Exit_IncrementalDiscovery -eq $discoveryType)
{
$oDiscoveryData.IsSnapshot = $false
}
}

return $oDiscoveryData

}

Function Get-PowerPlan
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()
$Filter = "IsActive=true"
$PowerPlan = ""

# Some group policies can restrict accessing to Win32_PowerPlan,
# need to handle it gracefully (for more information please see
# PS# 162496 in Server Management)

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$WMIPowerSet = Get-CimInstance -CimSession $cimsession -ClassName "Win32_PowerPlan" -Namespace "root\cimv2\power" -Filter $Filter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if(0 -ne $Error.Count)
{
$Error.Clear()
$WMIPowerSet = Get-WmiObject -Class "Win32_PowerPlan" -Namespace "root\cimv2\power" -Filter $Filter
}

if ($null -eq $WMIPowerSet)
{

return $PowerPlan
}

foreach ($oPlan in $WMIPowerSet)
{
$PowerPlan = $oPlan.ElementName
break
}

if ($error.Count -ne 0)
{
$PowerPlan = ""
}

return $PowerPlan
}

Main

</PowerShellScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</DataSource>
<!--
<DataSource ID="Scheduler" TypeID="System!System.Discovery.Scheduler">
<Scheduler>
<SimpleReccuringSchedule>
<Interval Unit="Seconds">$Config/IntervalSeconds$</Interval>
</SimpleReccuringSchedule>
<ExcludeDates />
</Scheduler>
</DataSource>
<ProbeAction ID="RegistryProbe" TypeID="Windows!Microsoft.Windows.RegistryProbe">
<ComputerName>$Target/Property[Type='Windows!Microsoft.Windows.Computer']/NetworkName$</ComputerName>
<RegistryAttributeDefinitions>
<RegistryAttributeDefinition>
<AttributeName>WindowsCurrentVersion</AttributeName>
<Path>SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion</Path>
<PathType>1</PathType>
<AttributeType>1</AttributeType>
</RegistryAttributeDefinition>
</RegistryAttributeDefinitions>
</ProbeAction>
<ProbeAction ID="ScriptProbe" TypeID="Microsoft.Windows.Server.10.0.PowerShellDiscoveryProbe">
<ScriptName>Microsoft.Windows.Server.10.0.Discovery.Probe.ps1</ScriptName>
<PSparam><![CDATA[param ($SourceID, $ManagedEntityId, $TargetComputer, $TargetComputerID, $boolIsVirtualNode)]]></PSparam>
<ScriptBody><Script>
<![CDATA[
<![CDATA[#Copyright (c) Microsoft Corporation. All rights reserved.

# Parameters that should be passed to this script
# 0 MPElement ID
# 1 Target Id for ME this rule is running against
# 2 Computer (FQDN) that the OS will be hosted on
# 3 Computer ID (Key) that the OS will be hosted on
# 4 IsVirtualNode

$Start_SnapShotDiscovery = 0
$Exit_SnapShotDiscovery = 1
$Exit_IncrementalDiscovery = 2

Function Main()
{

$result = Init-ScomHelper

if ($false -eq $result)
{
return
}

$oDiscoveryData = Get-DiscoveryData

if ($null -eq $oDiscoveryData)
{
return
}

$ErrorActionPreference = "SilentlyContinue"

$SerializeDiscoveryData = [Scom.Helper.ConvertData]::GetDataItemFromOutput($oDiscoveryData)
Write-Host "$SerializeDiscoveryData"
}

Function Load-CimModules
{
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()
}
}

Function DoDiscovery
{
param ([string]$sTargetComputer, [string]$sTargetComputerID, $oDisc)

$ErrorActionPreference = "SilentlyContinue"
$result = $false

$CoreFull = "Full"
$ComputerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Full.Computer']$"
$OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Full.OperatingSystem']$"
$InstallationType = GetRegistryKeyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" "InstallationType"

if ($InstallationType -eq "Server Core")
{
$CoreFull = "Core"
$ComputerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Core.Computer']$"
$OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Core.OperatingSystem']$"
}
elseif($InstallationType -eq "Nano Server")
{
$CoreFull = "Nano"
$ComputerClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Nano.Computer']$"
$OsClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Nano.OperatingSystem']$"
}

$Error.Clear()

$oInstanceComputer = $oDisc.CreateClassInstance($ComputerClassId)
$oInstanceOperatingSystem = $oDisc.CreateClassInstance($OsClassId)
if (0 -ne $Error.Count)
{
return $result
}

$PowerPlan = Get-PowerPlan
$Error.Clear()


$oInstanceComputer.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sTargetComputerID)
$oInstanceComputer.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Computer']/InstallType$", $CoreFull)
$oInstanceOperatingSystem.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sTargetComputerID)
$oInstanceOperatingSystem.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.OperatingSystem']/InstallType$", $CoreFull)
$oInstanceOperatingSystem.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.OperatingSystem']/PowerPlan$", $PowerPlan)

if (0 -ne $Error.Count)
{
return $result
}


$oDisc.AddInstance($oInstanceComputer)
$oDisc.AddInstance($oInstanceOperatingSystem)

$result = 0 -eq $Error.Count

return $result

}

Function Get-SnapshotDiscovery($OsVersion,$IsVirtualNode)
{
$ErrorActionPreference = "SilentlyContinue"

$bIsVirtualNode = Convert-ToBoolean -sBool $IsVirtualNode

if ($bIsVirtualNode)
{
return $Exit_SnapShotDiscovery
}

$Filter = "ProductType != 1"
$Error.Clear()

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$result = Get-CimInstance -CimSession $cimsession -ClassName "Win32_OperatingSystem" -Filter $Filter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if(0 -ne $Error.Count)
{
$Error.Clear()
$result = Get-WmiObject -Class "Win32_OperatingSystem" -Filter $Filter

if (0 -ne $Error.Count)
{
return $Exit_IncrementalDiscovery
}

}

if([string]::IsNullOrEmpty($OsVersion))
{
$OsVersion = "10\."
}

if ($null -eq $result -or -not ($result.Version -match $OsVersion))
{
$result = $Exit_SnapShotDiscovery
}
else
{
$result = $Start_SnapShotDiscovery
}

return $result
}

Function Get-DiscoveryData
{
$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
$oDiscoveryData = $momAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
if (0 -ne $Error.Count)
{
return $null
}

$discoveryType = Get-SnapshotDiscovery -OsVersion $VersionMask -IsVirtualNode $boolIsVirtualNode

If ($Start_SnapShotDiscovery -eq $discoveryType)
{
$result = DoDiscovery $TargetComputer $TargetComputerID $oDiscoveryData
if ($false -eq $result)
{
$Error.Clear()
$oDiscoveryData = $momAPI.CreateDiscoveryData(0, $SourceID, $ManagedEntityId)
$oDiscoveryData.IsSnapshot = $false
}
}
else
{
if ($Exit_IncrementalDiscovery -eq $discoveryType)
{
$oDiscoveryData.IsSnapshot = $false
}
}

return $oDiscoveryData

}

Function Get-PowerPlan
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()
$Filter = "IsActive=true"
$PowerPlan = ""

# Some group policies can restrict accessing to Win32_PowerPlan,
# need to handle it gracefully (for more information please see
# PS# 162496 in Server Management)

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$WMIPowerSet = Get-CimInstance -CimSession $cimsession -ClassName "Win32_PowerPlan" -Namespace "root\cimv2\power" -Filter $Filter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if(0 -ne $Error.Count)
{
$Error.Clear()
$WMIPowerSet = Get-WmiObject -Class "Win32_PowerPlan" -Namespace "root\cimv2\power" -Filter $Filter
}

if ($null -eq $WMIPowerSet)
{

return $PowerPlan
}

foreach ($oPlan in $WMIPowerSet)
{
$PowerPlan = $oPlan.ElementName
break
}

if ($error.Count -ne 0)
{
$PowerPlan = ""
}

return $PowerPlan
}

Main

]]>
]]>
</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>SourceID</Name>
<Value>$Config/SourceId$</Value>
</Parameter>
<Parameter>
<Name>ManagedEntityId</Name>
<Value>$Target/Id$</Value>
</Parameter>
<Parameter>
<Name>TargetComputer</Name>
<Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</Value>
</Parameter>
<Parameter>
<Name>TargetComputerID</Name>
<Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
</Parameter>
<Parameter>
<Name>boolIsVirtualNode</Name>
<Value>$Target/Property[Type="Windows!Microsoft.Windows.Server.Computer"]/IsVirtualNode$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>

</ProbeAction>
<ProbeAction ID="WMIProbe" TypeID="Windows!Microsoft.Windows.WmiProbe">
<NameSpace>\\$Target/Property[Type='Windows!Microsoft.Windows.Computer']/NetworkName$\root\cimv2</NameSpace>
<Query>select ProductType, Version from Win32_OperatingSystem</Query>
</ProbeAction>
<ConditionDetection ID="Filter" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Values/WindowsCurrentVersion</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">6.3</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
<ConditionDetection ID="Filter2" TypeID="System!System.ExpressionFilter">
<Expression>
<And>
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Integer">Property[@Name='ProductType']</XPathQuery>
</ValueExpression>
<Operator>NotEqual</Operator>
<ValueExpression>
<Value Type="Integer">1</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
<Expression>
<RegExExpression>
<ValueExpression>
<XPathQuery>Property[@Name='Version']</XPathQuery>
</ValueExpression>
<Operator>ContainsSubstring</Operator>
<Pattern>10.0.</Pattern>
</RegExExpression>
</Expression>
</And>
</Expression>
</ConditionDetection>
-->
</MemberModules>
<Composition>
<!--
<Node ID="ScriptProbe">
<Node ID="Filter2">
<Node ID="WMIProbe">
<Node ID="Filter">
<Node ID="RegistryProbe">
-->
<Node ID="Scheduler"/>
<!-- </Node>
</Node>
</Node>
</Node>

</Node>
-->
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>