Write Action Module: Start Service via WMI. (PowerShell)

Microsoft.Windows.Server.StartServiceViaWMI.ModuleType.PowerShell (WriteActionModuleType)

This write action module is used in the version specific operating system management packs for tasks.

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityPublic
RunAsSystem.PrivilegedMonitoringAccount
InputTypeSystem.BaseData
OutputTypeSystem.CommandOutput

Member Modules:

ID Module Type TypeId RunAs 
StartServiceViaWMI WriteAction System.CommandExecuter Default

Source Code:

<WriteActionModuleType ID="Microsoft.Windows.Server.StartServiceViaWMI.ModuleType.PowerShell" Accessibility="Public" RunAs="System!System.PrivilegedMonitoringAccount">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ComputerName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ServiceName" type="xsd:string"/>
</Configuration>
<OverrideableParameters/>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="StartServiceViaWMI" TypeID="System!System.CommandExecuter">
<ApplicationName>%windir%\system32\windowspowershell\v1.0\powershell.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>-command "&amp; '$File/Microsoft.Windows.Server.StartServiceViaWMI.ModuleType.ps1$' $Config/ComputerName$ $Config/ServiceName$"</CommandLine>
<TimeoutSeconds>300</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Microsoft.Windows.Server.StartServiceViaWMI.ModuleType.ps1</Name>
<Contents><Script>

param ([string] $TargetComputer, [string] $ServiceName)
$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"

$momAPI = new-object -comObject MOM.ScriptAPI
Import-Module CimCmdlets -ErrorAction SilentlyContinue

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

$DISKSIZE_BYTES_IN_MB = 1048576

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

$WIN_SRV_2012_OSVer = "6.2"
#******************************************************************************
# FUNCTION: CheckByOSCurrentVersion
# DESCRIPTION: Returns True if the Registry Key for CurrentVersion
# is equal the target OS Versions Number.
# RETURNS: Boolean: True, if build is greater or equal than the given number
#******************************************************************************
function CheckByOSCurrentVersion()
{
$strCurrentOSVer = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
$strCurrentOSVer = $strCurrentOSVer.CurrentVersion
$CheckByOSCurrentVersion = $false
if($strCurrentOSVer -ge $WIN_SRV_2012_OSVer){
$CheckByOSCurrentVersion = $true
}else{
$CheckByOSCurrentVersion = $false
}
return $CheckByOSCurrentVersion;
}

$useCIM = CheckByOSCurrentVersion

#---------------------------------------------------------------------------
# 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();
if($useCIM){
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
}
}else{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
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();
if($useCIM){

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
}
}else{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
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, $sInstanceQuery)

$error.Clear()

# !!! Refactoring comment:
# Original VBScript only tries to connect to the namespace. Piping to get only the first one saves time.
if($useCIM)
{
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
}
}else{
$oWMI = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue | select -First 1
}
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 $sInstanceQuery
$oInstance = WMIGetInstanceEx $sTargetComputer $sNamespace $sInstanceQuery
return $oInstance
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstanceNoAbort
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)
if($useCIM){
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
}
}else{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
return $oInstance
}

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

$error.Clear()

if($useCIM){

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
}
}else{
$oQuery = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}
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)
if($useCIM){
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
}
}else{
$oQuery = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}

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 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 Computer (FQDN) where the Server service should be started
# 1 Service Name

Function Main()
{
$ServiceState_Stopped = "stopped"
$ServiceState_Running = "running"

$owObj = GetServerService $TargetComputer $ServiceName

If ($owObj.State.ToLower() -ne $ServiceState_Stopped)
{
Write-Host ("The " + $owObj.DisplayName + " service is not stopped (" + $owObj.State + ").")
return
}

Write-Host ("The " + $owObj.DisplayName + " service is starting ...")

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$Result = Invoke-CimMethod -CimSession $cimsession -InputObject $owObj -MethodName StartService
}
catch
{
$Result = Invoke-WmiMethod -InputObject $owObj -Name StartService
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
Verify ($Result.ReturnValue -eq 0) ("Could not start the " + $owObj.DisplayName + " service with error " + $Result.ReturnValue + " (" + (GetServiceErrorCode $Result.ReturnValue) + ").")

$nCount = 10
do
{
sleep -m 1000
$owObj = GetServerService $TargetComputer $ServiceName
Write-Host ("Current state is '" + $owObj.State + "'.")
$nCount--
}
while ($owObj.State.ToLower() -ne $ServiceState_Running -and $nCount -ge 0)

If ($owObj.State.ToLower() -eq $ServiceState_Running)
{
Write-Host ("The " + $owObj.DisplayName + " service was started successfully.")
}
}

Function GetServerService
{
param ([string]$sTargetComputer,
[string]$sServiceName)

$WMISet = WMIGetInstance $sTargetComputer "root\cimv2" ("Win32_Service where Name='" + $sServiceName + "'")
Verify ($WMISet -isnot [System.Array]) ("Invalid quantity of services with name '" + $sServiceName + "' (qty = " + $WMISet.Count + ").")
foreach ($owObj in $WMISet)
{
return $owObj
}
}

Function GetServiceErrorCode
{
param ([Int]$Code)
$varArray = New-Object string[] 25
$varArray[0] = "Success"
$varArray[1] = "Not Supported"
$varArray[2] = "Access Denied"
$varArray[3] = "Dependent Services Running"
$varArray[4] = "Invalid Service Control"
$varArray[5] = "Service Cannot Accept Control"
$varArray[6] = "Service Not Active"
$varArray[7] = "Service Request Timeout"
$varArray[8] = "Unknown Failure"
$varArray[9] = "Path Not Found"
$varArray[10] = "Service Already Running"
$varArray[11] = "Service Database Locked"
$varArray[12] = "Service Dependency Deleted"
$varArray[13] = "Service Dependency Failure"
$varArray[14] = "Service Disabled"
$varArray[15] = "Service Logon Failure"
$varArray[16] = "Service Marked For Deletion"
$varArray[17] = "Service No Thread"
$varArray[18] = "Status Circular Dependency"
$varArray[19] = "Status Duplicate Name"
$varArray[20] = "Status Invalid Name"
$varArray[21] = "Status Invalid Parameter"
$varArray[22] = "Status Invalid Service Account"
$varArray[23] = "Status Service Exists"
$varArray[24] = "Service Already Paused"

If (($Code -lt 0) -or ($Code -ge $varArray.Length))
{
return "Unknown Code Result"
}

return $varArray[$Code]
}
Function Load-CimModules
{
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()
}
}
Main</Script></Contents>
</File>
</Files>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="StartServiceViaWMI"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.CommandOutput</OutputType>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>