Analyse de découverte du script PowerShell

Microsoft.Windows.Server.10.0.PowerShellDiscoveryProbe (ProbeActionModuleType)

Utilisez ce module au sein d'une composition dans un type de module de source de données personnalisé, qui est utilisé dans les workflows de découverte et se sert d'un script PowerShell pour effectuer la découverte.

Element properties:

TypeProbeActionModuleType
IsolationAny
AccessibilityPublic
RunAsDefault
InputTypeSystem.BaseData
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
PowerShellPA ProbeAction Microsoft.Windows.PowerShellDiscoveryProbe Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
TimeoutSecondsint$Config/TimeoutSeconds$Délai d'expiration (secondes)

Source Code:

<ProbeActionModuleType ID="Microsoft.Windows.Server.10.0.PowerShellDiscoveryProbe" Accessibility="Public" Batching="false">
<Configuration>
<IncludeSchemaTypes>
<SchemaType>Windows!Microsoft.Windows.PowerShellSchema</SchemaType>
</IncludeSchemaTypes>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ScriptName" type="NonNullString"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="PSparam" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ScriptBody" type="NonNullString"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SnapIns" type="SnapInsType" minOccurs="0" maxOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Parameters" type="NamedParametersType" minOccurs="0" maxOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StrictErrorHandling" type="xsd:boolean" minOccurs="0" maxOccurs="1"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="PowerShellPA" TypeID="Windows!Microsoft.Windows.PowerShellDiscoveryProbe">
<ScriptName>$Config/ScriptName$</ScriptName>
<ScriptBody><Script>

$Config/PSparam$
$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()
}
}
$Config/ScriptBody$

</Script></ScriptBody>
<SnapIns>$Config/SnapIns$</SnapIns>
<Parameters>$Config/Parameters$</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<StrictErrorHandling>$Config/StrictErrorHandling$</StrictErrorHandling>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="PowerShellPA"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>