Windows Server 2012 R2 Discovery (Discovery)

Microsoft.Windows.Server.2012.R2.Discovery.DataSource (DataSourceModuleType)

This data source discovers Windows Server 2012 R2.

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsSystem.PrivilegedMonitoringAccount
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource System.CommandExecuterDiscoveryDataSource Default

Overrideable Parameters:

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

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Server.2012.R2.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"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="Scheduler" TypeID="System!System.CommandExecuterDiscoveryDataSource">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<ApplicationName>%SystemRoot%\system32\cmd.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>/c $file/Main.cmd$</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Main.cmd</Name>
<Contents><Script>

@echo off
set psscript=Microsoft.Windows.Server.2012.R2.Discovery.Probe.ps1
set vbscript=Microsoft.Windows.Server.2012.R2.Discovery.Probe.vbs
set cscript=%windir%\system32\cscript.exe
set ps=%windir%\system32\WindowsPowerShell\v1.0\powershell.exe
set params=

if Exist "%cscript%" goto vb
if Exist "%ps%" goto pshell
goto end
:vb
if not exist "%~dp0%vbscript%" goto end

if exist "%~dp0vbparams.txt" (
set /p params=&lt;"%~dp0vbparams.txt"
)

"%cscript%" /nologo "%~dp0%vbscript%" %params%
goto end
:pshell
if not exist "%~dp0%psscript%" goto end

if exist "%~dp0psparams.txt" (
set /p params=&lt;"%~dp0psparams.txt"
)
"%ps%" -nologo -EP bypass -command "&amp; '%~dp0%psscript%'" %params%
goto end

:end



</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>Microsoft.Windows.Server.2012.R2.Discovery.Probe.ps1</Name>
<Contents><Script>

param($SourceId, $ManagedEntityId, $TargetComputer, $TargetComputerID, $boolIsVirtualNode)

Function Init-ScomHelper
{
$DiscHelper = @'
namespace SCOM.Helper
{
using System;
using System.Runtime.InteropServices;
public class ConvertData
{

public static string GetDataItemFromOutput(
Object oData)
{
NativeMethods.ISerialize discoverySerializer = null;
discoverySerializer = oData as NativeMethods.ISerialize;
string xmlString = null;
if (null != discoverySerializer)
{
int hr = discoverySerializer.SaveToString(out xmlString);
Marshal.ThrowExceptionForHR(hr);
}

return xmlString;
}

public static class NativeMethods
{
[Guid("A4E79E8A-9494-47A4-A280-8C7D35C88A2F"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISerialize
{
int SaveToString([MarshalAs(UnmanagedType.BStr)] out string output);
int LoadFromString([MarshalAs(UnmanagedType.BStr)] string input);
}
}
}
}

'@

$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
Add-Type $DiscHelper

$result = 0 -eq $Error.Count

return $result
}#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

$VersionPrefix = "6.3"
$Start_SnapShotDiscovery = 0
$Exit_SnapShotDiscovery = 1
$Exit_IncrementalDiscovery = 2
$SKUDatacenterServerCoreEdition = 12
$SKUStandardServerCoreEdition = 13
$SKUEnterpriseServerCoreEdition = 14

$momAPI = new-object -comObject MOM.ScriptAPI

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

$CimModule = Get-Module CimCmdlets

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

}
}

Function Main()
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()

$result = Init-ScomHelper

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

$oDiscoveryData = Get-DiscoveryData

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


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

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

$ErrorActionPreference = "SilentlyContinue"
$result = $false

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

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

$error.Clear()

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

$Error.Clear()

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

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

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


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

$result = 0 -eq $Error.Count

return $result

}

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-OsFilter([string]$OSVersion,[string]$delimiter=",")
{
$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()

$Filter = "ProductType != 1"

if([string]::IsNullOrEmpty($OsVersion))
{
return $Filter
}
$prefix = " and (Version like '"
$separator = "%' or Version like '"
$EndClause = "%')"

$OsVersions = $OSVersion.Split($delimiter,[StringSplitOptions]::RemoveEmptyEntries)
if ($OsVersions.Count -eq 0 -or $null -eq $OsVersions )
{
return $Filter
}

$SubFilter = [string]::Join($separator,$OsVersions)
$Filter = $Filter + $prefix + $SubFilter + $EndClause

return $Filter
}

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

$bIsVirtualNode = Convert-ToBoolean -sBool $IsVirtualNode

if ($bIsVirtualNode)
{
return $Exit_SnapShotDiscovery
}

$Filter = Get-OsFilter -OSVersion $OsVersion
$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 ($null -eq $result)
{
$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 $VersionPrefix -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)
$WMIPowerSet = Get-WmiObject -Class "Win32_PowerPlan" -Namespace "root\cimv2\power" -Filter $Filter

if(0 -ne $Error.Count)
{
$Error.Clear()

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 ($null -eq $WMIPowerSet)
{
$error.Clear()
return $PowerPlan
}

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

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

return $PowerPlan
}

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

$ErrorActionPreference = "SilentlyContinue"
$error.Clear()
$result = ""
$strKeyValue = Get-ItemProperty -Path $keyPath -Name $key

if ($error.Count -eq 0)
{
$result = $strKeyValue.$key
}

$error.Clear()

return $result
}


if ($null -eq $momAPI)
{
exit
}


Load-CimModules

Main

</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>Microsoft.Windows.Server.2012.R2.Discovery.Probe.vbs</Name>
<Contents><Script>
'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

Set oReg = MOMCreateObject("WScript.Shell")
On Error Resume Next

strKeyValue = oReg.RegRead(keyPath &amp; key)
If Err.Number &lt;&gt; 0 Then
ThrowScriptError "An error occurred while reading the registry: '" &amp; keyPath &amp; key &amp; "'", Err.Description
strKeyValue = ""
End If

' resume error
On Error Goto 0

GetRegistryKeyValue = strKeyValue
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


'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 Windows Current Version (6.0 - Server 2008, 6.1 - Server 2008 R2, 6.2 - Server 2012, 6.3 - Server vNext)
' 5 IsVirtualNode

Const OSVersion = "6.3"
Const Start_SnapShotDiscovery = 0
Const Exit_SnapShotDiscovery = 1
Const Exit_IncrementalDiscovery = 2

Call Main()

Sub Main()

Dim oArgs
Set oArgs = WScript.Arguments
Dim SourceID, ManagedEntityId, TargetComputer, TargetComputerID, WindowsCurrentVersion, boolIsVirtualNode

If (oArgs.Count &lt; 4 ) Then
ThrowScriptError "Wrong number of arguments.", Null
Exit Sub
End If

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

If (oArgs.Count &lt; 5) Then
boolIsVirtualNode = ""
Else
boolIsVirtualNode = UCase(oArgs(4) )
End If


Dim oAPI, oDiscoveryData,result,oError,boolResult

'Check for conditions if not meet return empty discovery data
result = GetSnapshotDiscovery(OSVersion,boolIsVirtualNode)
Set oAPI = MOMCreateObject("MOM.ScriptAPI")

On Error Resume Next
Err.Clear
Set oError = New Error
Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceID, ManagedEntityId)
If (Err.Number &lt;&gt; 0) Then
oError.Save
ThrowScriptError "Unable to create discovery data object ", oError
End If

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

Call oAPI.Return(oDiscoveryData)
On Error Goto 0
End Sub

Function DoDiscovery(ByVal sTargetComputer, ByVal sTargetComputerID, ByVal oDisc)
Dim oInstanceComputer, oInstanceOperatingSystem, InstallationType, IsCore, CoreFull, WMIPowerSet, oPlan, PowerPlan
Dim computerClassId, OsClassId
'If current version is not 6.3 (Windows Server vNext) then no discovery will be executed
'Registry Key InstallionType exists only in Windows Server vNext OS
DoDiscovery = False

InstallationType = GetRegistryKeyValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "InstallationType")
computerClassId = "$MPElement[Name='Microsoft.Windows.Server.2012.R2.Full.Computer']$"
OsClassId = "$MPElement[Name='Microsoft.Windows.Server.2012.R2.Full.OperatingSystem']$"
CoreFull = "Full"

If (InstallationType = "Server Core") Then
computerClassId = "$MPElement[Name='Microsoft.Windows.Server.2012.R2.Core.Computer']$"
OsClassId = "$MPElement[Name='Microsoft.Windows.Server.2012.R2.Core.OperatingSystem']$"
CoreFull = "Core"
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)
On Error Resume Next
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 = ""
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


With oInstanceComputer
.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sTargetComputerID
.AddProperty "$MPElement[Name='WindowsServer!Microsoft.Windows.Server.6.2.Computer']/InstallType$", CoreFull
End With
With oInstanceOperatingSystem
.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sTargetComputerID
.AddProperty "$MPElement[Name='WindowsServer!Microsoft.Windows.Server.6.2.OperatingSystem']/InstallType$", CoreFull
.AddProperty "$MPElement[Name='WindowsServer!Microsoft.Windows.Server.6.2.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 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 GetOsFilter(strOSVersion,delimiter)

On Error Resume Next
Err.Clear

Dim Filter,Prefix,Separator,EndClause
Dim OsVersions,SubFilter

Filter = " where ProductType != 1"
GetOSFilter = Filter

If (Not HasValue(strOSVersion) or 0 = Len(strOSVersion)) Then
Exit Function
End If
If (Not HasValue(delimiter)) Then
delimiter = ","
End If

If (delimiter = strOSVersion) Then
Exit Function
End If

Prefix = " and (Version like '"
Separator = "%' or Version like '"
EndClause = "%')"

OsVersions = Split(strOSVersion,delimiter)

SubFilter = Join(OsVersions,Separator)
Filter = Filter &amp; Prefix &amp; SubFilter &amp; EndClause

GetOSFilter = Filter
On Error Goto 0
End Function

Function GetServerOsVersionCheck(sComputerName, OsVersions,ByRef IsError)

On Error Resume Next

Err.Clear

Dim strQuery,oWmiSet, sWmiTarget, Count, Filter,OsData
IsError = False
GetServerOsVersionCheck = False

If ( IsObject(OsVersions)) 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"
Filter = GetOsFilter(OsVersions,",")
StrQuery = "select Version from Win32_OperatingSystem" + Filter
Set oWmiSet = WMIExecQueryNoAbort(sWmiTarget, strQuery)

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

Count = oWmiSet.Count
If Err.Number &lt;&gt; 0 Then
IsError = True
Exit Function
End If

GetServerOsVersionCheck = ( Count &gt; 0)

On Error Goto 0
End Function

Function GetSnapshotDiscovery(OsVersions,IsVirtualNode)

Dim bIsOsValid,bIsError,iResult

On Error Resume Next

If IsEmpty(IsVirtualNode) = True Or IsVirtualNode = "" Or IsVirtualNode = "FALSE" Then
bIsOsValid = GetServerOsVersionCheck(".",OsVersions,bIsError)

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

End If

Else
iResult = Exit_SnapShotDiscovery
End If

GetSnapshotDiscovery = iResult
End Function
</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>vbparams.txt</Name>
<Contents><Script>"$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$"</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>psparams.txt</Name>
<Contents><Script>'$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$'</Script></Contents>
<Unicode>false</Unicode>
</File>
</Files>
</DataSource>
</MemberModules>
<Composition>
<Node ID="Scheduler"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>