Skip to content

Commit a8ef6ac

Browse files
committed
Test Target Resource now works reasonably well
1 parent 46d294b commit a8ef6ac

File tree

2 files changed

+158
-37
lines changed

2 files changed

+158
-37
lines changed

source/DSCResources/DSC_xServiceResource/DSC_xServiceResource.psm1

Lines changed: 157 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

source/DSCResources/DSC_xServiceResource/en-US/DSC_xServiceResource.strings.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ ConvertFrom-StringData @'
3737
CannotGetAccountAccessErrorMessage = Failed to get user policy rights.
3838
CannotSetAccountAccessErrorMessage = Failed to set user policy rights.
3939
CorruptDependency = Service '{0}' has a corrupt dependency. For more information, inspect the registry value at HKLM:\\SYSTEM\\CurrentControlSet\\Services\\{0}\\DependOnService.
40+
FailureActionsMustBeSpecifiedInOrder = Failure actions must be specified in order from 1 to 3.
4041
'@

0 commit comments

Comments
 (0)