Private/Update-GpoVersion.ps1

# UpdateGpt on file GpoPrivilegeRights.cs
function Update-GpoVersion {

    <#
        .SYNOPSIS
            Updates the version number of a specified Group Policy Object (GPO).

        .DESCRIPTION
            The Update-GpoVersion function increments the computer version number of a specified GPO by 3. It updates both the directory object and the GPT.INI file in the SYSVOL share.

        .PARAMETER GpoName
            The name of the GPO to be updated.

        .EXAMPLE
            Update-GpoVersion -GpoName "Default Domain Policy"

        .INPUTS
            GPO Name.

        .OUTPUTS
            None.
    #>


    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [OutputType([void])]

    param (
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = 'Specify the name of the GPO.',
            Position = 0)]
        [string]
        $GpoName
    )

    Begin {
        $txt = ($Variables.HeaderDelegation -f
            (Get-Date).ToShortDateString(),
            $MyInvocation.Mycommand,
            (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False)
        )
        Write-Verbose -Message $txt

        ##############################
        # Module imports
        Import-MyModule -Name 'GroupPolicy' -SkipEditionCheck -Verbose:$false

        ##############################
        # Variables Definition
        [Int64]$versionObject = $null

        # Retrieve the GPO object by name
        $gpo = Get-GPO -Name $PsBoundParameters['GpoName'] -ErrorAction Stop
        # Get the GPO ID
        $gpoId = ('{' + $gpo.Id + '}')
        # Build SYSVOL path
        $sysVolPath = '\\{0}\SYSVOL\{0}' -f $env:USERDNSDOMAIN
        $pathToGpt = '{0}\Policies\{1}\gpt.ini' -f $sysVolPath, $gpoId

    } #end Begin

    Process {

        Try {

            # Get the GPO object
            $url = 'LDAP://CN={0},CN=Policies,CN=System,{1}' -f $gpoId, $Variables.defaultNamingContext
            $de = [System.DirectoryServices.DirectoryEntry]::New($url)

        } catch {

            Write-Error -Message ('Error accessing GPO through DirectoryEntry' -f $Gpo.Name)
            #Get-ErrorDetail -ErrorRecord $_

        } #end Try-Catch

        # Get the VersionObject of the DirectoryEntry (the GPO)
        $versionObject = [Int64]($de.Properties['VersionNumber'].Value.ToString())
        Write-Verbose -Message ('Old GPO Version Number: {0}' -f $versionObject)

        # Convert the value into a 8 digit HEX string
        $hexValue = $versionObject.ToString('x8')

        # Top 16 bits HEX UserVersionNumber - first 4 characters (complete with zero to the left)
        # This is the UserVersion
        $hexUserVN = $hexValue.Substring(0, 4)

        # Lower 16 bits HEX ComputerVersionNumber - last 4 characters (complete with zero to the left)
        # This is the ComputerVersion
        $hexComputerVN = $hexValue.Substring(4)

        # Lower 16 bits as Integer ComputerVersionNumber
        $computerVN = [Convert]::ToInt64($hexComputerVN, 16)

        # Increment Computer Version Number by 3
        $computerVN += 3

        # Concatenate '0x' and 'HEX UserVersionNumber having 4 digits' and 'HEX ComputerVersionNumber having 4 digits'
        $newHex = '0x{0}{1}' -f $hexUserVN, $computerVN.ToString('x4')

        # Convert the New Hex number to integer
        $newVersionObject = [Convert]::ToInt64($newHex, 16)


        try {

            if ($PSCmdlet.ShouldProcess($GpoName, 'Update GPO version')) {
                # Update the GPO VersionNumber with the new value
                $de.Properties['VersionNumber'].Value = $newVersionObject.ToString()

                # Last, write the GPCMachineExtensionName attribute with the Client-Side Extension GUID
                # If not the settings won't display in the GPO Management tool and the target
                # server won't be able to read the GPO.
                $de.Properties['gPCMachineExtensionNames'].Value = '[{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]'

                # Save the information on the DirectoryObject
                $de.CommitChanges()

                # Close the DirectoryEntry
                $de.Close()

                # Write new version value to GPT (Including Section Name)
                if (Test-Path -Path $pathToGpt) {

                    # New instance of IniFile class
                    $Gpt = [IniFileHandler.IniFile]::new($pathToGpt)
                    #$Gpt.ReadFile($pathToGpt)

                    # Check section exists
                    if ($Gpt.SectionExists('General')) {
                        Write-Verbose -Message ('Section Name: General')

                        # Change value of an existing key
                        $Gpt.SetKeyValue('General', 'Version', $newVersionObject.ToString())
                        $Gpt.SetKeyValue('General', 'displayName', $Gpo.DisplayName)

                    } else {
                        Write-Verbose -Message 'Section [General] does not exist. Creating it with Key=Value.'

                        $Gpt.AddSection('General')

                        # Add a new Key/Value pair within a given section
                        $Gpt.SetKeyValue('General', 'Version', $newVersionObject.ToString())
                        $Gpt.SetKeyValue('General', 'displayName', $Gpo.DisplayName)
                    } #end If-Else

                    # Save file using default encoding UTF-8
                    $Gpt.SaveFile($pathToGpt)

                    Write-Verbose -Message ('Saving new Version of GPO to file {0}' -f $pathToGpt)
                } #end If
            } #end If
        } catch {
            #Get-ErrorDetail -ErrorRecord $_
            throw "The GPTs.ini file could not be modified: $_. Message is $($_.Exception.Message)"
        } #end Try-Catch

    } #end Process

    End {
        $txt = ($Variables.FooterDelegation -f $MyInvocation.InvocationName,
            'Version of GPO updated (Private Function).'
        )
        Write-Verbose -Message $txt
    } #end End
}