PropósitoCuando añadimos un PC al dominio se va al contendor "Computers" que no es una OU a la que se puedan asignar GPOs.
Esto implica el riesgo que no se les apliquen ninguna GPO, con lo que hay esta atentos para moverlos a su OU correspondiente.
El script que aquí pondré lo ejecuto una vez al día (Tarea programada) y le envío copia al equipo de Help Desk. Básicamente mira si hay algún hosts en el contenedor de Computers y si lo hay envía un email informando.
No modifica nada, solo es informativa.
Pasos
Básicamente mira si hay algún hosts en el contenedor de Computers y si lo hay envía un email informando
<#
Busca equipos en el contenedor CN=Computers.
Si hay equipos → envía correo con la tabla HTML en el CUERPO.
Si no hay equipos → no envía correo.
#>
# ==========================
# VARIABLES DEL USUARIO
# ==========================
$SMTPServer = "
miservidor.midominio.com
"
$SMTPPort = 25
$From = "Servidor1
@midominio.com"
$To = "
itsecurity@midominio.com" , "HelpDesk@midominio.com
",
$Subject = "PCs en la Ou de Computers"
# Contenedor donde buscar (CORRECTO)
$SearchBase = "CN=Computers,DC=midominio,DC=com"
# ==========================
# CARGAR MÓDULO AD
# ==========================
if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) {
Write-Error "El módulo ActiveDirectory no está disponible. Instala RSAT."
exit 1
}
Import-Module ActiveDirectory
# ==========================
# VALIDAR CONTENEDOR
# ==========================
try {
$null = Get-ADObject -Identity $SearchBase -ErrorAction Stop
}
catch {
Write-Error "ERROR: No se encontró el contenedor/OU: $SearchBase"
exit 1
}
# ==========================
# OBTENER EQUIPOS
# ==========================
$Computers = Get-ADComputer -SearchBase $SearchBase `
-SearchScope OneLevel `
-Filter * `
-Properties Name, DNSHostName, Description, OperatingSystem, Enabled, LastLogonDate, whenCreated, whenChanged
$Count = $Computers.Count
Write-Host "Equipos encontrados: $Count"
if ($Count -eq 0) {
Write-Host "Contenedor vacío. No se envía correo."
exit 0
}
# ==========================
# GENERAR HTML
# ==========================
$Sorted = $Computers | Sort-Object Name
$Table = $Sorted | Select-Object `
@{n="Nombre (sAM)"; e={$_.Name}},
@{n="Hostname (DNS)"; e={$_.DNSHostName}},
@{n="Descripción"; e={ if ($_.Description) { $_.Description } else { "N/D" } }},
@{n="SO"; e={$_.OperatingSystem}},
@{n="Habilitado"; e={$_.Enabled}},
@{n="Último logon"; e={ if ($_.LastLogonDate) { $_.LastLogonDate } else { "N/D" } }},
@{n="Creado"; e={$_.whenCreated}},
@{n="Modificado"; e={$_.whenChanged}} |
ConvertTo-Html -As Table -Fragment
$Style = @"
<style>
body { font-family: Segoe UI, Arial; color:#222; }
table { border-collapse: collapse; width:100%; }
th, td { border: 1px solid #ccc; padding:6px; }
th { background:#f0f0f0; }
tr:nth-child(even) { background:#fafafa; }
.notice { font-weight:bold; color:#b00020; }
</style>
"@
$IntroText = "<p class='notice'>Estos PC deben moverse a la OU correspondiente</p>"
$Header = "<h2>Equipos encontrados en: $SearchBase</h2>"
$BodyHtml = ConvertTo-Html -Head $Style -Body "$IntroText $Header $Table"
# ==========================
# ENVIAR CORREO
# ==========================
try {
$Mail = New-Object System.Net.Mail.MailMessage
$Mail.From = $From
foreach ($recipient in $To) {
if ($recipient.Trim()) { $Mail.To.Add($recipient.Trim()) }
}
$Mail.Subject = $Subject + " (Total: $Count)"
$Mail.IsBodyHtml = $true
$Mail.Body = $BodyHtml
$SMTP = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort)
$SMTP.Send($Mail)
Write-Host "Correo enviado correctamente."
}
catch {
Write-Error "Error enviando el correo: $($_.Exception.Message)"
exit 1
}
El resultado vendría ser algo parecido a lo siguiente
Dificultad: Baja
Utilidad: Alta
by GoN | Published: Feb 2026 | Last Updated: