@@ -100,11 +100,14 @@ function Get-TargetResource
100100 DesktopInteract = $serviceCimInstance.DesktopInteract
101101 Dependencies = $dependencies
102102 ResetPeriodSeconds = $serviceFailureActions.resetPeriodSeconds
103- RebootCommand = $serviceFailureActions.rebootCommand
103+ FailureCommand = $serviceFailureActions.failureCommand
104104 RebootMessage = $serviceFailureActions.rebootMessage
105- failureAction1 = $serviceFailureActions.failureAction1
106- failureAction2 = $serviceFailureActions.failureAction2
107- failureAction3 = $serviceFailureActions.failureAction3
105+ failure1Action = $serviceFailureActions.failureAction1.actionType
106+ failure1Delay = $serviceFailureActions.failureAction1.delay
107+ failure2Action = $serviceFailureActions.failureAction2.actionType
108+ failure2Delay = $serviceFailureActions.failureAction2.delay
109+ failure3Action = $serviceFailureActions.failureAction3.actionType
110+ failure3Delay = $serviceFailureActions.failureAction3.delay
108111 }
109112 }
110113 else
@@ -513,6 +516,42 @@ function Test-TargetResource
513516 [System.UInt32 ]
514517 $TerminateTimeout = 30000 ,
515518
519+ [Parameter ()]
520+ [System.UInt32 ]
521+ $ResetPeriodSeconds ,
522+
523+ [Parameter ()]
524+ [System.String ]
525+ $RebootMessage ,
526+
527+ [Parameter ()]
528+ [System.String ]
529+ $FailureCommand ,
530+
531+ [Parameter ()]
532+ [ACTION _TYPE ]
533+ $Failure1Action ,
534+
535+ [Parameter ()]
536+ [System.UInt32 ]
537+ $Failure1Delay ,
538+
539+ [Parameter ()]
540+ [ACTION _TYPE ]
541+ $Failure2Action ,
542+
543+ [Parameter ()]
544+ [System.UInt32 ]
545+ $Failure2Delay ,
546+
547+ [Parameter ()]
548+ [ACTION _TYPE ]
549+ $Failure3Action ,
550+
551+ [Parameter ()]
552+ [System.UInt32 ]
553+ $Failure3Delay ,
554+
516555 [Parameter ()]
517556 [ValidateNotNull ()]
518557 [System.Management.Automation.PSCredential ]
@@ -534,6 +573,14 @@ function Test-TargetResource
534573 New-InvalidArgumentException - ArgumentName ' BuiltInAccount / Credential / GroupManagedServiceAccount' - Message $errorMessage
535574 }
536575
576+ if (($PSBoundParameters.ContainsKey (' Failure3Action' ) -and (-not $PSBoundParameters.ContainsKey (' Failure2Action' ))) -or
577+ ($PSBoundParameters.ContainsKey (' Failure2Action' ) -and (-not $PSBoundParameters.ContainsKey (' Failure1Action' )))
578+ )
579+ {
580+ $errorMessage = $script :localizedData.FailureActionsMustBeSpecifiedInOrder
581+ New-InvalidArgumentException - ArgumentName ' Failure2Action / Failure3Action' - Message $errorMessage
582+ }
583+
537584 $serviceResource = Get-TargetResource - Name $Name
538585
539586 if ($serviceResource.Ensure -eq ' Absent' )
@@ -654,6 +701,69 @@ function Test-TargetResource
654701 Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' State' , $Name , $State , $serviceResource.State )
655702 return $false
656703 }
704+
705+ # Check the reset period
706+ if ($PSBoundParameters.ContainsKey (' ResetPeriodSeconds' ) -and $ResetPeriodSeconds -ine $serviceResource.ResetPeriodSeconds )
707+ {
708+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' ResetPeriodSeconds' , $Name , $ResetPeriodSeconds , $serviceResource.ResetPeriodSeconds )
709+ return $false
710+ }
711+
712+ # Check the failure command
713+ if ($PSBoundParameters.ContainsKey (' FailureCommand' ) -and $FailureCommand -ine $serviceResource.failureCommand )
714+ {
715+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' FailureCommand' , $Name , $FailureCommand , $serviceResource.failureCommand )
716+ return $false
717+ }
718+
719+ # Check the reboot message
720+ if ($PSBoundParameters.ContainsKey (' RebootMessage' ) -and $RebootMessage -ine $serviceResource.rebootMessage )
721+ {
722+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' RebootMessage' , $Name , $RebootMessage , $serviceResource.rebootMessage )
723+ return $false
724+ }
725+
726+ # Check the failure 1 action
727+ if ($PSBoundParameters.ContainsKey (' Failure1Action' ) -and $Failure1Action -ine $serviceResource.failure1Action )
728+ {
729+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' Failure1Action' , $Name , $Failure1Action , $serviceResource.failure1Action )
730+ return $false
731+ }
732+
733+ # Check failure 1 delay
734+ if ($PSBoundParameters.ContainsKey (' Failure1Delay' ) -and $Failure1Delay -ine $serviceResource.failure1Delay )
735+ {
736+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' Failure1Delay' , $Name , $Failure1Delay , $serviceResource.failure1Delay )
737+ return $false
738+ }
739+
740+ # Check the failure 2 action
741+ if ($PSBoundParameters.ContainsKey (' Failure2Action' ) -and $Failure2Action -ine $serviceResource.failure2Action )
742+ {
743+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' Failure2Action' , $Name , $Failure2Action , $serviceResource.failure2Action )
744+ return $false
745+ }
746+
747+ # Check failure 2 delay
748+ if ($PSBoundParameters.ContainsKey (' Failure2Delay' ) -and $Failure2Delay -ine $serviceResource.failure2Delay )
749+ {
750+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' Failure2Delay' , $Name , $Failure2Delay , $serviceResource.failure2Delay )
751+ return $false
752+ }
753+
754+ # Check the failure 3 action
755+ if ($PSBoundParameters.ContainsKey (' Failure3Action' ) -and $Failure3Action -ine $serviceResource.failure3Action )
756+ {
757+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' Failure3Action' , $Name , $Failure3Action , $serviceResource.failure3Action )
758+ return $false
759+ }
760+
761+ # Check failure 3 delay
762+ if ($PSBoundParameters.ContainsKey (' Failure3Delay' ) -and $Failure3Delay -ine $serviceResource.failure3Delay )
763+ {
764+ Write-Verbose - Message ($script :localizedData.ServicePropertyDoesNotMatch -f ' Failure3Delay' , $Name , $Failure3Delay , $serviceResource.failure3Delay )
765+ return $false
766+ }
657767 }
658768
659769 return $true
@@ -1911,57 +2021,67 @@ function Get-ServiceFailureActions {
19112021 )
19122022 process {
19132023 $registryData = Get-Item HKLM:\SYSTEM\CurrentControlSet\Services\$service
1914- $failureActionsBinaryData = $registryData.GetValue (' FailureActions' )
19152024
19162025 $failureActions = [PSCustomObject ]@ {
2026+ resetPeriodSeconds = $null
2027+ hasRebootMessage = $null
2028+ hasFailureCommand = $null
2029+ failureActionCount = $null
2030+ failureCommand = $null
2031+ rebootMessage = $null
2032+ failureAction1 = @ {actionType = $null ; delay = $null }
2033+ failureAction2 = @ {actionType = $null ; delay = $null }
2034+ failureAction3 = @ {actionType = $null ; delay = $null }
2035+ }
2036+
2037+ if ($registryData.GetvalueNames () -match ' FailureCommand' ) {
2038+ $failureActions.failureCommand = $registryData.GetValue (' FailureCommand' )
2039+ }
2040+
2041+ if ($registryData.GetValueNames () -match ' RebootMessage' ) {
2042+ $failureActions.rebootMessage = $registryData.GetValue (' RebootMessage' )
2043+ }
2044+
2045+ if ($registryData.GetValueNames () -match ' FailureActions' )
2046+ {
2047+ $failureActionsBinaryData = $registryData.GetValue (' FailureActions' )
2048+
19172049 # The first four bytes represent the Reset Period. The bytes are little endian
19182050 # so they are reversed, converted to hex, and then cast to an integer.
1919- resetPeriodSeconds = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 0
2051+ $failureActions . resetPeriodSeconds = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 0
19202052
1921- # The next four bytes represent a true or false indicating whether a reboot message exists.
1922- # If one does exist, it's value is held in a different value.
1923- hasRebootMessage = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 1
2053+ # Next found bytes indicate the presence of a reboot message in case one of the chosen failure actions is
2054+ # SC_ACTION_REBOOT. The actual value of the message is stored in the 'RebootMessage' property
2055+ $failureActions . hasRebootMessage = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 1
19242056
19252057 # The next four bytes indicate whether a failure action run command exists. This command
19262058 # would be run in the case one of the failure actions chosen is SC_ACTION_RUN_COMMAND
19272059 # If this value is true then the actual command string is stored in a different value.
1928- hasRebootCommand = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 2
2060+ $failureActions .hasFailureCommand = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 2
19292061
19302062 # These four bytes give the count of how many reboot failure actions have been defined.
19312063 # Up to three actions may be defined.
1932- failureActionCount = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 3
1933- rebootCommand = $null
1934- rebootMessage = $null
1935- failureAction1 = @ {actionType = $null ; delay = $null }
1936- failureAction2 = @ {actionType = $null ; delay = $null }
1937- failureAction3 = @ {actionType = $null ; delay = $null }
1938- }
2064+ $failureActions.failureActionCount = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - Offset 3
19392065
1940- if ($failureActions.failureActionCount -gt 0 ) {
1941- foreach ($item in 1 .. $failureActions.failureActionCount ) {
2066+ if ($failureActions.failureActionCount -gt 0 ) {
2067+ foreach ($item in 1 .. $failureActions.failureActionCount ) {
19422068
1943- $offset = switch ($item ) {
1944- 1 { 5 }
1945- 2 { 7 }
1946- 3 { 9 }
1947- Default {-1 }
2069+ # Manually counting the array offset is easier than implementing some weird array arithmetic.
2070+ $offset = switch ($item ) {
2071+ 1 { 5 }
2072+ 2 { 7 }
2073+ 3 { 9 }
2074+ Default {-1 }
2075+ }
2076+ # Occasionaly a service will store an array acount greater than 3. As far as I can tell
2077+ # A count greater than 3 has no meaning, so we only support 3.
2078+ if ($offset -lt 0 ) { break }
2079+ $failureActions ." failureAction$item " .actionType = [ACTION _TYPE ](Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - offset $offset )
2080+ $failureActions ." failureAction$item " .delay = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - offset ($offset + 1 )
19482081 }
1949- # Occasionaly a service will store an array acount greater than 3. As far as I can tell
1950- # A count greater than 3 has no meaning, so we only support 3.
1951- if ($offset -lt 0 ) { break }
1952- $failureActions ." failureAction$item " .actionType = [ACTION _TYPE ](Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - offset $offset )
1953- $failureActions ." failureAction$item " .delay = Convert-RegistryBinaryValueToInt - Bytes $failureActionsBinaryData - offset ($offset + 1 )
19542082 }
19552083 }
19562084
1957- if ($failureActions.hasRebootCommand ) {
1958- $failureActions.rebootCommand = $registryData.GetValue (' FailureCommand' )
1959- }
1960-
1961- if ($failureActions.hasRebootMessage ) {
1962- $failureActions.rebootMessage = $registryData.GetValue (' RebootMessage' )
1963- }
1964-
19652085 $failureActions
19662086 }
19672087}
0 commit comments