#requires -Version 5.1
<#
Crea o actualiza una GPO para ejecutar scripts/inventtory.ps1 al arrancar los equipos.
Opcionalmente concede el derecho de apagado remoto a una cuenta o grupo del dominio.
Opcionalmente habilita Escritorio remoto para usuarios o grupos del dominio.
Opcionalmente habilita la ejecucion de trabajos remotos de la consola de software.

Ejecutar desde un controlador de dominio o un equipo con RSAT/GroupPolicy y permisos para
crear/enlazar GPOs. Por defecto crea la GPO y copia el agente a SYSVOL; solo la enlaza si
se indica -Target o -LinkAtDomainRoot.
#>

[CmdletBinding(SupportsShouldProcess = $true)]
param(
    [string]$GpoName = 'Intranet - Inventario de equipos',
    [string]$Domain = $env:USERDNSDOMAIN,
    [string]$Target = '',
    [switch]$LinkAtDomainRoot,
    [string]$SourceScript = (Join-Path $PSScriptRoot 'inventtory.ps1'),
    [string]$AgentFolder = 'intranet-inventario',
    [string]$AgentScriptName = 'inventtory.ps1',
    [string]$Endpoint = '',
    [string]$Token = '',
    [switch]$SkipSoftware,
    [switch]$RunDeployments,
    [int]$TimeoutSec = 120,
    [switch]$Enforced,
    [switch]$Disabled,
    [Alias('RemoteShutdownPrincipals')]
    [string[]]$RemoteShutdownPrincipal = @(),
    [switch]$EnableRemoteDesktop,
    [Alias('RemoteDesktopPrincipals')]
    [string[]]$RemoteDesktopPrincipal = @()
)

$ErrorActionPreference = 'Stop'

function Resolve-DomainName {
    param([string]$Value)

    if (-not [string]::IsNullOrWhiteSpace($Value)) {
        return $Value.Trim().ToLowerInvariant()
    }

    try {
        return ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name.ToLowerInvariant()
    } catch {
        throw 'No se pudo detectar el dominio. Ejecuta dentro del dominio o usa -Domain midominio.local.'
    }
}

function ConvertTo-DomainDistinguishedName {
    param([Parameter(Mandatory = $true)][string]$DomainName)

    $parts = $DomainName.Split('.') | Where-Object { $_ -ne '' }
    if ($parts.Count -lt 2) {
        throw "El dominio '$DomainName' debe estar en formato DNS, por ejemplo dominio.local."
    }

    return 'DC=' + ($parts -join ',DC=')
}

function ConvertTo-QuotedPsString {
    param([string]$Value)
    if ($null -eq $Value) {
        $Value = ''
    }
    return "'" + ($Value -replace "'", "''") + "'"
}

function New-StartupCommandContent {
    param(
        [Parameter(Mandatory = $true)][string]$ScriptUnc,
        [string]$EndpointValue,
        [string]$TokenValue,
        [bool]$UseSkipSoftware,
        [bool]$EnableDeployments,
        [int]$RequestTimeoutSec,
        [bool]$ConfigureRemoteDesktop,
        [string[]]$RemoteDesktopPrincipalSids
    )

    $lines = New-Object System.Collections.Generic.List[string]
    $lines.Add('$ErrorActionPreference = ''Stop''')
    if ($ConfigureRemoteDesktop) {
        $sidLiterals = @($RemoteDesktopPrincipalSids | ForEach-Object { ConvertTo-QuotedPsString $_ })
        $lines.Add('$rdpPrincipalSids = @(' + ($sidLiterals -join ', ') + ')')
        $lines.Add('try {')
        $lines.Add('    New-Item -Path ''HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'' -Force | Out-Null')
        $lines.Add('    New-ItemProperty -Path ''HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'' -Name ''fDenyTSConnections'' -PropertyType DWord -Value 0 -Force | Out-Null')
        $lines.Add('    New-Item -Path ''HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'' -Force | Out-Null')
        $lines.Add('    New-ItemProperty -Path ''HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'' -Name ''UserAuthentication'' -PropertyType DWord -Value 1 -Force | Out-Null')
        $lines.Add('    if (Get-Command Get-NetFirewallRule -ErrorAction SilentlyContinue) {')
        $lines.Add('        Get-NetFirewallRule -Name ''RemoteDesktop-*'' -ErrorAction SilentlyContinue | Enable-NetFirewallRule -ErrorAction SilentlyContinue')
        $lines.Add('    }')
        $lines.Add('    $rdpGroupName = (New-Object System.Security.Principal.SecurityIdentifier(''S-1-5-32-555'')).Translate([System.Security.Principal.NTAccount]).Value.Split(''\'', 2)[1]')
        $lines.Add('    foreach ($sid in $rdpPrincipalSids) {')
        $lines.Add('        try {')
        $lines.Add('            $memberName = (New-Object System.Security.Principal.SecurityIdentifier($sid)).Translate([System.Security.Principal.NTAccount]).Value')
        $lines.Add('            try {')
        $lines.Add('                Add-LocalGroupMember -Group $rdpGroupName -Member $memberName -ErrorAction Stop')
        $lines.Add('            } catch {')
        $lines.Add('                $result = & net.exe localgroup $rdpGroupName $memberName /add 2>&1')
        $lines.Add('                if ($LASTEXITCODE -ne 0 -and (($result -join '' '') -notmatch ''1378|already|existe|ya es'')) { throw ($result -join '' '') }')
        $lines.Add('            }')
        $lines.Add('        } catch {')
        $lines.Add('            Write-Warning (''No se pudo configurar RDP para SID '' + $sid + '': '' + $_.Exception.Message)')
        $lines.Add('        }')
        $lines.Add('    }')
        $lines.Add('    Set-Service -Name ''TermService'' -StartupType Manual -ErrorAction SilentlyContinue')
        $lines.Add('    Start-Service -Name ''TermService'' -ErrorAction SilentlyContinue')
        $lines.Add('} catch {')
        $lines.Add('    Write-Warning (''No se pudo habilitar Escritorio remoto: '' + $_.Exception.Message)')
        $lines.Add('}')
    }
    $lines.Add('$script = ' + (ConvertTo-QuotedPsString $ScriptUnc))
    $lines.Add('$params = @{}')
    if (-not [string]::IsNullOrWhiteSpace($EndpointValue)) {
        $lines.Add('$params.Endpoint = ' + (ConvertTo-QuotedPsString $EndpointValue))
    }
    if (-not [string]::IsNullOrWhiteSpace($TokenValue)) {
        $lines.Add('$params.Token = ' + (ConvertTo-QuotedPsString $TokenValue))
    }
    if ($UseSkipSoftware) {
        $lines.Add('$params.SkipSoftware = $true')
    }
    if ($EnableDeployments) {
        $lines.Add('$params.RunDeployments = $true')
    }
    if ($RequestTimeoutSec -gt 0) {
        $lines.Add('$params.TimeoutSec = ' + [string]$RequestTimeoutSec)
    }
    $lines.Add('& $script @params')

    $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes(($lines -join "`r`n")))
    return @(
        '@echo off'
        'set "LOGDIR=%ProgramData%\IntranetInventario"'
        'if not exist "%LOGDIR%" mkdir "%LOGDIR%" >nul 2>&1'
        'powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ' + $encoded + ' >> "%LOGDIR%\startup.log" 2>&1'
        'exit /b %ERRORLEVEL%'
    ) -join "`r`n"
}

function Get-OrCreateGpo {
    param(
        [Parameter(Mandatory = $true)][string]$Name,
        [Parameter(Mandatory = $true)][string]$DomainName
    )

    try {
        $existing = Get-GPO -Name $Name -Domain $DomainName -ErrorAction Stop
        Write-Host "GPO existente: $Name"
        return $existing
    } catch {
        if ($PSCmdlet.ShouldProcess($Name, 'Crear GPO')) {
            $created = New-GPO -Name $Name -Domain $DomainName
            Write-Host "GPO creada: $Name"
            return $created
        }
        throw 'Operacion cancelada por WhatIf.'
    }
}

function Read-GptVersion {
    param([Parameter(Mandatory = $true)][string]$GptIniPath)

    if (-not (Test-Path -LiteralPath $GptIniPath)) {
        return 0
    }

    $raw = Get-Content -Raw -LiteralPath $GptIniPath
    if ($raw -match '(?im)^Version=(\d+)\s*$') {
        return [int]$matches[1]
    }

    return 0
}

function Update-GptVersion {
    param(
        [Parameter(Mandatory = $true)][string]$GptIniPath,
        [Parameter(Mandatory = $true)][int]$Version
    )

    $content = if (Test-Path -LiteralPath $GptIniPath) {
        Get-Content -Raw -LiteralPath $GptIniPath
    } else {
        "[General]`r`nVersion=0`r`n"
    }

    if ($content -match '(?im)^Version=\d+\s*$') {
        $content = [regex]::Replace($content, '(?im)^Version=\d+\s*$', 'Version=' + $Version, 1)
    } else {
        $content = $content.TrimEnd() + "`r`nVersion=$Version`r`n"
    }

    Set-Content -LiteralPath $GptIniPath -Value $content -Encoding ASCII
}

function Get-NextMachineGpoVersion {
    param([int]$CurrentVersion)

    $userVersion = ($CurrentVersion -shr 16) -band 0xffff
    $machineVersion = ($CurrentVersion -band 0xffff) + 1
    if ($machineVersion -gt 0xffff) {
        $machineVersion = 1
    }

    return ($userVersion -shl 16) -bor $machineVersion
}

function Wait-PathAvailable {
    param(
        [Parameter(Mandatory = $true)][string]$Path,
        [int]$TimeoutSec = 30
    )

    $deadline = (Get-Date).AddSeconds($TimeoutSec)
    do {
        if (Test-Path -LiteralPath $Path) {
            return
        }
        Start-Sleep -Seconds 1
    } while ((Get-Date) -lt $deadline)

    throw "No se encontro la ruta esperada en SYSVOL: $Path"
}

function Add-PrivilegeValue {
    param(
        [Parameter(Mandatory = $true)][System.Collections.Generic.List[string]]$Values,
        [Parameter(Mandatory = $true)][hashtable]$Seen,
        [string]$Value
    )

    $item = ([string]$Value).Trim()
    if ($item -eq '') {
        return
    }

    $key = $item.ToUpperInvariant()
    if (-not $Seen.ContainsKey($key)) {
        $Seen[$key] = $true
        $Values.Add($item) | Out-Null
    }
}

function Resolve-PrincipalSidValue {
    param([Parameter(Mandatory = $true)][string]$Principal)

    return '*' + (Resolve-PrincipalSidText -Principal $Principal)
}

function Resolve-PrincipalSidText {
    param([Parameter(Mandatory = $true)][string]$Principal)

    $value = $Principal.Trim()
    if ($value -eq '') {
        throw 'La cuenta o grupo no puede estar vacio.'
    }

    if ($value -match '^\*?S-\d-\d+(-\d+)+$') {
        if ($value.StartsWith('*')) {
            return $value.Substring(1)
        }
        return $value
    }

    try {
        $account = New-Object System.Security.Principal.NTAccount($value)
        $sid = $account.Translate([System.Security.Principal.SecurityIdentifier]).Value
        return $sid
    } catch {
        throw "No se pudo resolver '$value' a SID. Usa DOMINIO\usuario, DOMINIO\grupo o un SID valido."
    }
}

function Resolve-DomainSidText {
    param([Parameter(Mandatory = $true)][string]$DomainDn)

    try {
        $domainEntry = [ADSI]("LDAP://$DomainDn")
        $bytes = $domainEntry.Properties['objectSid'].Value
        return (New-Object System.Security.Principal.SecurityIdentifier($bytes, 0)).Value
    } catch {
        throw "No se pudo resolver el SID del dominio desde LDAP://$DomainDn. Detalle: $($_.Exception.Message)"
    }
}

function Test-SecurityTemplateSection {
    param(
        [Parameter(Mandatory = $true)][System.Collections.Generic.List[string]]$Lines,
        [Parameter(Mandatory = $true)][string]$Name
    )

    $target = "[$Name]"
    foreach ($line in $Lines) {
        if ($line.Trim().Equals($target, [System.StringComparison]::OrdinalIgnoreCase)) {
            return $true
        }
    }
    return $false
}

function Set-GpoPrivilegeRight {
    param(
        [Parameter(Mandatory = $true)][string]$GpoRoot,
        [Parameter(Mandatory = $true)][string]$PrivilegeName,
        [Parameter(Mandatory = $true)][string[]]$Principals
    )

    $securityRoot = Join-Path $GpoRoot 'Machine\Microsoft\Windows NT\SecEdit'
    $templatePath = Join-Path $securityRoot 'GptTmpl.inf'
    New-Item -ItemType Directory -Path $securityRoot -Force | Out-Null

    $lines = New-Object System.Collections.Generic.List[string]
    if (Test-Path -LiteralPath $templatePath) {
        foreach ($line in Get-Content -LiteralPath $templatePath) {
            $lines.Add($line) | Out-Null
        }
    }

    if ($lines.Count -eq 0) {
        $lines.Add('[Unicode]') | Out-Null
        $lines.Add('Unicode=yes') | Out-Null
        $lines.Add('') | Out-Null
        $lines.Add('[Version]') | Out-Null
        $lines.Add('signature="$CHICAGO$"') | Out-Null
        $lines.Add('Revision=1') | Out-Null
    }

    if (-not (Test-SecurityTemplateSection -Lines $lines -Name 'Unicode')) {
        $lines.Insert(0, '')
        $lines.Insert(0, 'Unicode=yes')
        $lines.Insert(0, '[Unicode]')
    }

    if (-not (Test-SecurityTemplateSection -Lines $lines -Name 'Version')) {
        $lines.Add('') | Out-Null
        $lines.Add('[Version]') | Out-Null
        $lines.Add('signature="$CHICAGO$"') | Out-Null
        $lines.Add('Revision=1') | Out-Null
    }

    $resolvedPrincipals = New-Object System.Collections.Generic.List[string]
    foreach ($principal in $Principals) {
        if (-not [string]::IsNullOrWhiteSpace($principal)) {
            $resolvedPrincipals.Add((Resolve-PrincipalSidValue -Principal $principal)) | Out-Null
        }
    }

    $privilegeLineIndex = -1
    $privilegePattern = '^\s*' + [regex]::Escape($PrivilegeName) + '\s*=\s*(.*)$'
    $values = New-Object System.Collections.Generic.List[string]
    $seen = @{}

    for ($i = 0; $i -lt $lines.Count; $i++) {
        if ($lines[$i] -match $privilegePattern) {
            $privilegeLineIndex = $i
            foreach ($existingValue in ($matches[1] -split ',')) {
                Add-PrivilegeValue -Values $values -Seen $seen -Value $existingValue
            }
            break
        }
    }

    Add-PrivilegeValue -Values $values -Seen $seen -Value '*S-1-5-32-544'
    foreach ($sidValue in $resolvedPrincipals) {
        Add-PrivilegeValue -Values $values -Seen $seen -Value $sidValue
    }

    $newLine = $PrivilegeName + ' = ' + ($values -join ',')

    if ($privilegeLineIndex -ge 0) {
        $lines[$privilegeLineIndex] = $newLine
    } else {
        $sectionIndex = -1
        for ($i = 0; $i -lt $lines.Count; $i++) {
            if ($lines[$i].Trim().Equals('[Privilege Rights]', [System.StringComparison]::OrdinalIgnoreCase)) {
                $sectionIndex = $i
                break
            }
        }

        if ($sectionIndex -lt 0) {
            $lines.Add('') | Out-Null
            $lines.Add('[Privilege Rights]') | Out-Null
            $sectionIndex = $lines.Count - 1
        }

        $insertIndex = $lines.Count
        for ($i = $sectionIndex + 1; $i -lt $lines.Count; $i++) {
            if ($lines[$i].Trim() -match '^\[.+\]$') {
                $insertIndex = $i
                break
            }
        }
        $lines.Insert($insertIndex, $newLine)
    }

    Set-Content -LiteralPath $templatePath -Value ($lines -join "`r`n") -Encoding Unicode
}

function Update-GpoAdMetadata {
    param(
        [Parameter(Mandatory = $true)][string]$DomainDn,
        [Parameter(Mandatory = $true)][string]$GpoGuidText,
        [Parameter(Mandatory = $true)][int]$Version,
        [bool]$EnableSecuritySettings = $false
    )

    $ldapPath = "LDAP://CN=$GpoGuidText,CN=Policies,CN=System,$DomainDn"
    $gpc = [ADSI]$ldapPath

    $currentExtensions = ''
    if ($gpc.Properties['gPCMachineExtensionNames'].Count -gt 0) {
        $currentExtensions = [string]$gpc.Properties['gPCMachineExtensionNames'].Value
    }

    $extensionPairs = @(
        @{
            Marker = '{42B5FAAE-6536-11D2-AE5A-0000F87571E3}'
            Pair = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'
        }
    )
    if ($EnableSecuritySettings) {
        $extensionPairs += @{
            Marker = '{827D319E-6EAC-11D2-A4EA-00C04F79F83A}'
            Pair = '[{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]'
        }
    }

    foreach ($extension in $extensionPairs) {
        if ($currentExtensions -notlike ('*' + $extension.Marker + '*')) {
            $currentExtensions += $extension.Pair
        }
    }

    $gpc.Put('gPCMachineExtensionNames', $currentExtensions)
    $gpc.Put('versionNumber', $Version)
    $gpc.SetInfo()
}

function Set-GpoStartupScript {
    param(
        [Parameter(Mandatory = $true)][string]$GpoRoot,
        [Parameter(Mandatory = $true)][string]$StartupCommandContent
    )

    $scriptsRoot = Join-Path $GpoRoot 'Machine\Scripts'
    $startupRoot = Join-Path $scriptsRoot 'Startup'
    $shutdownRoot = Join-Path $scriptsRoot 'Shutdown'
    $startupCommandName = 'run-inventario.cmd'
    $startupCommandPath = Join-Path $startupRoot $startupCommandName
    $scriptsIniPath = Join-Path $scriptsRoot 'scripts.ini'

    New-Item -ItemType Directory -Path $startupRoot -Force | Out-Null
    New-Item -ItemType Directory -Path $shutdownRoot -Force | Out-Null
    Set-Content -LiteralPath $startupCommandPath -Value $StartupCommandContent -Encoding ASCII
    Set-Content -LiteralPath $scriptsIniPath -Value "[Startup]`r`n0CmdLine=$startupCommandName`r`n0Parameters=`r`n" -Encoding ASCII
}

$Domain = Resolve-DomainName $Domain
$DomainDn = ConvertTo-DomainDistinguishedName $Domain

if ($LinkAtDomainRoot.IsPresent -and -not [string]::IsNullOrWhiteSpace($Target)) {
    throw 'Usa -Target o -LinkAtDomainRoot, pero no ambos a la vez.'
}

if (-not (Test-Path -LiteralPath $SourceScript)) {
    throw "No se encuentra el script de inventario: $SourceScript"
}

$RemoteShutdownPrincipal = @($RemoteShutdownPrincipal | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
$configureRemoteShutdown = $RemoteShutdownPrincipal.Count -gt 0
$RemoteDesktopPrincipal = @($RemoteDesktopPrincipal | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
$remoteDesktopPrincipalSids = @()
if ($EnableRemoteDesktop.IsPresent) {
    if ($RemoteDesktopPrincipal.Count -eq 0) {
        $remoteDesktopPrincipalSids = @((Resolve-DomainSidText -DomainDn $DomainDn) + '-513')
    } else {
        $remoteDesktopPrincipalSids = @($RemoteDesktopPrincipal | ForEach-Object { Resolve-PrincipalSidText -Principal $_ })
    }
}

Import-Module GroupPolicy -ErrorAction Stop

$sysvolRoot = "\\$Domain\SYSVOL\$Domain"
if (-not (Test-Path -LiteralPath $sysvolRoot)) {
    throw "No se puede acceder a SYSVOL: $sysvolRoot"
}

$gpo = Get-OrCreateGpo -Name $GpoName -DomainName $Domain
$gpoGuid = if ($gpo.Id -is [guid]) { $gpo.Id } else { [guid]$gpo.Id }
$gpoGuidText = '{' + $gpoGuid.ToString().ToUpperInvariant() + '}'
$gpoRoot = Join-Path $sysvolRoot "Policies\$gpoGuidText"
$gptIniPath = Join-Path $gpoRoot 'GPT.INI'
Wait-PathAvailable -Path $gpoRoot -TimeoutSec 30

$agentRoot = Join-Path $sysvolRoot "scripts\$AgentFolder"
$agentPath = Join-Path $agentRoot $AgentScriptName
$agentUnc = "\\$Domain\SYSVOL\$Domain\scripts\$AgentFolder\$AgentScriptName"

if ($PSCmdlet.ShouldProcess($agentUnc, 'Copiar agente de inventario')) {
    New-Item -ItemType Directory -Path $agentRoot -Force | Out-Null
    Copy-Item -LiteralPath $SourceScript -Destination $agentPath -Force
}

$startupCommand = New-StartupCommandContent `
    -ScriptUnc $agentUnc `
    -EndpointValue $Endpoint `
    -TokenValue $Token `
    -UseSkipSoftware $SkipSoftware.IsPresent `
    -EnableDeployments $RunDeployments.IsPresent `
    -RequestTimeoutSec $TimeoutSec `
    -ConfigureRemoteDesktop $EnableRemoteDesktop.IsPresent `
    -RemoteDesktopPrincipalSids $remoteDesktopPrincipalSids

if ($PSCmdlet.ShouldProcess($GpoName, 'Configurar directivas de equipo')) {
    Set-GpoStartupScript -GpoRoot $gpoRoot -StartupCommandContent $startupCommand
    if ($configureRemoteShutdown) {
        Set-GpoPrivilegeRight -GpoRoot $gpoRoot -PrivilegeName 'SeRemoteShutdownPrivilege' -Principals $RemoteShutdownPrincipal
    }
    $nextVersion = Get-NextMachineGpoVersion -CurrentVersion (Read-GptVersion -GptIniPath $gptIniPath)
    Update-GptVersion -GptIniPath $gptIniPath -Version $nextVersion
    Update-GpoAdMetadata -DomainDn $DomainDn -GpoGuidText $gpoGuidText -Version $nextVersion -EnableSecuritySettings $configureRemoteShutdown
}

$linkTarget = ''
if ($LinkAtDomainRoot.IsPresent) {
    $linkTarget = $DomainDn
} elseif (-not [string]::IsNullOrWhiteSpace($Target)) {
    $linkTarget = $Target.Trim()
}

if ($linkTarget -ne '') {
    $linkEnabled = if ($Disabled.IsPresent) { 'No' } else { 'Yes' }
    $enforcedValue = if ($Enforced.IsPresent) { 'Yes' } else { 'No' }

    if ($PSCmdlet.ShouldProcess($linkTarget, "Enlazar GPO '$GpoName'")) {
        try {
            New-GPLink -Name $GpoName -Domain $Domain -Target $linkTarget -LinkEnabled $linkEnabled -Enforced $enforcedValue | Out-Null
        } catch {
            Set-GPLink -Name $GpoName -Domain $Domain -Target $linkTarget -LinkEnabled $linkEnabled -Enforced $enforcedValue | Out-Null
        }
    }
}

Write-Host ''
Write-Host 'Despliegue preparado.'
Write-Host "GPO: $GpoName"
Write-Host "Dominio: $Domain"
Write-Host "Agente: $agentUnc"
if ($configureRemoteShutdown) {
    Write-Host ("Apagado remoto: SeRemoteShutdownPrivilege concedido a " + ($RemoteShutdownPrincipal -join ', '))
}
if ($EnableRemoteDesktop.IsPresent) {
    if ($RemoteDesktopPrincipal.Count -gt 0) {
        Write-Host ("Escritorio remoto: habilitado para " + ($RemoteDesktopPrincipal -join ', '))
    } else {
        Write-Host 'Escritorio remoto: habilitado para Domain Users del dominio.'
    }
}
if ($RunDeployments.IsPresent) {
    Write-Host 'Trabajos remotos: habilitados para el agente de inventario.'
}
if ($linkTarget -ne '') {
    Write-Host "Enlace: $linkTarget"
} else {
    Write-Host 'Enlace: no configurado. Usa -Target "OU=Equipos,DC=dominio,DC=local" o -LinkAtDomainRoot.'
}
Write-Host 'Los equipos aplicaran la GPO en el siguiente refresco de directivas o reinicio.'
