DSCResources/MSFT_RefreshRegistryPolicy/MSFT_RefreshRegistryPolicy.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
$script:resourceModulePath = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
$script:modulesFolderPath = Join-Path -Path $script:resourceModulePath -ChildPath 'Modules'

$script:resourceHelperModulePath = Join-Path -Path $script:modulesFolderPath -ChildPath 'GPRegistryPolicyDsc.Common'
Import-Module -Name (Join-Path -Path $script:resourceHelperModulePath -ChildPath 'GPRegistryPolicyDsc.Common.psm1')

$script:localizedData = Get-LocalizedData -ResourceName 'MSFT_RefreshRegistryPolicy'

<#
    .SYNOPSIS
        Returns the current state if a machine requires a group policy refresh.
 
    .PARAMETER Name
        A name to serve as the key property. It is not used during configuration.
#>

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance
    )

    $refreshKeyValue = Read-GPRefreshRegistryKey

    Write-Verbose -Message ($script:localizedData.RefreshRequiredValue -f $refreshKeyValue.Value)

    return @{
        IsSingleInstance = 'Yes'
        Path               = $refreshKeyValue.Path
        RefreshRequiredKey = $refreshKeyValue.Value
    }
}

<#
    .SYNOPSIS
        Invokes gpupdate.exe /force to update group policy.
 
    .PARAMETER Name
        A name to serve as the key property. It is not used during configuration.
#>

function Set-TargetResource
{
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '',
        Justification = 'Suppressing this rule because $global:DSCMachineStatus is used to trigger a reboot')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '',
        Justification = 'Suppressing this rule because $global:DSCMachineStatus is used to trigger a reboot')]
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance
    )

    Write-Verbose -Message $script:localizedData.RefreshingGroupPolicy

    $gpupdateResult = Invoke-Command -ScriptBlock {'N','N' | gpupdate.exe /force}

    Remove-Item -Path HKLM:\SOFTWARE\Microsoft\GPRegistryPolicy -Force

    if ($gpupdateResult -match 'restart|log\soff')
    {
        Write-Warning -Message ($script:localizedData.RebootRequired)
        $global:DSCMachineStatus = 1
    }
}

<#
    .SYNOPSIS
        Reads the value of HKLM:\SOFTWARE\Microsoft\GPRegistryPolicy\RefreshRequired to determine if a group policy refresh is required.
 
    .PARAMETER Name
        A name to serve as the key property. It is not used during configuration.
#>

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance
    )

    $getTargetResourceResult = Get-TargetResource @PSBoundParameters

    if ($getTargetResourceResult.RefreshRequiredKey -ne 1)
    {
        Write-Verbose -Message $script:localizedData.NotRefreshRequired
        return $true
    }

    Write-Verbose -Message $script:localizedData.RefreshRequired

    return $false
}

<#
    .SYNOPSIS
        Writes a registry key indicating a group policy refresh is required.
 
    .PARAMETER Path
        Specifies the value of the registry path that will contain the properties pertaining to requiring a refresh.
 
    .PARAMETER PropertyName
        Specifies a name for the new property.
#>

function Read-GPRefreshRegistryKey
{
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param
    (
        [Parameter()]
        [System.String]
        $Path = 'HKLM:\SOFTWARE\Microsoft\GPRegistryPolicy',

        [Parameter()]
        [System.String]
        $PropertyName = 'RefreshRequired'
    )

    $registryKey = Get-Item -Path $Path -ErrorAction SilentlyContinue

    [PSCustomObject]@{
        Path  = $registryKey.Name
        Value = ($registryKey | Get-ItemProperty).$PropertyName
    }
}