[CmdletBinding(SupportsShouldProcess)] param( [string]$TargetOuDn = 'OU=Laboratorio,DC=lci,DC=lasalle,DC=mx', [string]$GpoName = 'SGU - Windows client experience', [string]$DomainController = $env:COMPUTERNAME ) $ErrorActionPreference = 'Stop' $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = [Security.Principal.WindowsPrincipal]::new($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Run this script from an elevated Windows PowerShell session on a domain controller or management host.' } Import-Module ActiveDirectory -ErrorAction Stop Import-Module GroupPolicy -ErrorAction Stop $targetOu = Get-ADOrganizationalUnit ` -Identity $TargetOuDn ` -Server $DomainController ` -ErrorAction Stop $domainDn = ($targetOu.DistinguishedName -split ',DC=', 2)[1] if (-not $domainDn) { throw 'TargetOuDn does not contain a domain distinguished name.' } $domainName = ($domainDn -replace ',DC=', '.') $gpo = Get-GPO -Name $GpoName -Domain $domainName -Server $DomainController -ErrorAction SilentlyContinue if (-not $gpo -and $PSCmdlet.ShouldProcess($GpoName, 'Create the SGU Windows client policy GPO')) { $gpo = New-GPO -Name $GpoName -Domain $domainName -Server $DomainController } if (-not $gpo) { throw "The GPO '$GpoName' does not exist and was not created." } $existingLink = @(Get-GPInheritance -Target $TargetOuDn -Domain $domainName -Server $DomainController).GpoLinks | Where-Object DisplayName -eq $GpoName | Select-Object -First 1 $existingLinkEnabled = $existingLink -and ( $existingLink.Enabled -eq $true -or [string]$existingLink.Enabled -eq 'Yes') if (-not $existingLink) { if ($PSCmdlet.ShouldProcess($TargetOuDn, "Link and enable '$GpoName'")) { New-GPLink ` -Name $GpoName ` -Target $TargetOuDn ` -Domain $domainName ` -Server $DomainController ` -LinkEnabled Yes | Out-Null } } elseif (-not $existingLinkEnabled -and $PSCmdlet.ShouldProcess($TargetOuDn, "Enable the '$GpoName' link")) { Set-GPLink ` -Name $GpoName ` -Target $TargetOuDn ` -Domain $domainName ` -Server $DomainController ` -LinkEnabled Yes | Out-Null } $dataCollectionKey = 'HKLM\Software\Policies\Microsoft\Windows\DataCollection' $powerPolicyRoot = 'HKLM\Software\Policies\Microsoft\Power\PowerSettings' $credentialProviderPolicyKey = 'HKLM\Software\Policies\Microsoft\Windows\System' $interactiveLogonPolicyKey = 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System' $accountPicturePolicyKey = 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' $providerClassId = '{D789CFD8-5AD4-489F-9B83-7EB5D9D09335}' $policies = @( @{ Key = $dataCollectionKey; Name = 'AllowTelemetry'; Type = 'DWord'; Value = 0 }, @{ Key = $dataCollectionKey; Name = 'DisableTelemetryOptInSettingsUx'; Type = 'DWord'; Value = 1 }, @{ Key = $dataCollectionKey; Name = 'DisableTelemetryOptInChangeNotification'; Type = 'DWord'; Value = 1 }, @{ Key = $dataCollectionKey; Name = 'DisableDiagnosticDataViewer'; Type = 'DWord'; Value = 1 }, @{ Key = 'HKLM\Software\Policies\Microsoft\Windows\OOBE'; Name = 'DisablePrivacyExperience'; Type = 'DWord'; Value = 1 }, @{ Key = $interactiveLogonPolicyKey; Name = 'EnableFirstLogonAnimation'; Type = 'DWord'; Value = 0 }, @{ Key = 'HKLM\Software\Policies\Microsoft\Windows\LocationAndSensors'; Name = 'DisableLocation'; Type = 'DWord'; Value = 1 }, @{ Key = 'HKLM\Software\Policies\Microsoft\Windows\AppPrivacy'; Name = 'LetAppsAccessLocation'; Type = 'DWord'; Value = 2 }, # Enrollment selects the provider before domain join; this computer GPO # becomes the authoritative, self-healing configuration afterwards. @{ Key = $credentialProviderPolicyKey; Name = 'DefaultCredentialProvider'; Type = 'String'; Value = $providerClassId }, @{ Key = $credentialProviderPolicyKey; Name = 'EnumerateLocalUsers'; Type = 'DWord'; Value = 0 }, @{ Key = $interactiveLogonPolicyKey; Name = 'DontDisplayLastUserName'; Type = 'DWord'; Value = 1 }, # Use Windows' native default account image for named user tiles. LogonUI # retains ownership of the anonymous Other user tile and its circular mask. @{ Key = $accountPicturePolicyKey; Name = 'UseDefaultTile'; Type = 'DWord'; Value = 1 } ) $powerSettingIds = @( '3c0bc021-c8a8-4e07-a973-6b14cbcb2b7e', # Turn off display after '29f6c1db-86da-48c5-9fdb-f2b67b1f44da', # Sleep after '9d7815a6-7ee4-497e-8888-515a05f02364', # Hibernate after '94ac6d29-73ce-41a6-809f-6363ba21b47e' # Allow hybrid sleep ) foreach ($settingId in $powerSettingIds) { $settingKey = "$powerPolicyRoot\$settingId" $policies += @{ Key = $settingKey; Name = 'ACSettingIndex'; Type = 'DWord'; Value = 0 } $policies += @{ Key = $settingKey; Name = 'DCSettingIndex'; Type = 'DWord'; Value = 0 } } foreach ($policy in $policies) { if ($PSCmdlet.ShouldProcess($GpoName, "Set $($policy.Key)\$($policy.Name)=$($policy.Value)")) { Set-GPRegistryValue ` -Name $GpoName ` -Domain $domainName ` -Server $DomainController ` -Key $policy.Key ` -ValueName $policy.Name ` -Type $policy.Type ` -Value $policy.Value | Out-Null } } $configuredPolicies = [ordered]@{} foreach ($policy in $policies) { $configured = Get-GPRegistryValue ` -Name $GpoName ` -Domain $domainName ` -Server $DomainController ` -Key $policy.Key ` -ValueName $policy.Name $configuredPolicies[$policy.Name + '@' + $policy.Key] = $configured.Value } $link = @(Get-GPInheritance -Target $TargetOuDn -Domain $domainName -Server $DomainController).GpoLinks | Where-Object DisplayName -eq $GpoName | Select-Object -First 1 $linkEnabled = $link -and ( $link.Enabled -eq $true -or [string]$link.Enabled -eq 'Yes') [pscustomobject]@{ GpoName = $GpoName GpoId = $gpo.Id TargetOu = $TargetOuDn LinkEnabled = [bool]$linkEnabled PolicyCount = $configuredPolicies.Count Policies = [pscustomobject]$configuredPolicies }