Compatibilidad con Windows 11 : audite sus equipos con PowerShell
Table of Contents
I. Introducción
Para muchas empresas, la migración de Windows 10 a Windows 11 es uno de los principales proyectos de este año 2025. Esta actualización, que puede llevarse a cabo utilizando diversas soluciones técnicas, también implica una fase de auditoría. Esta permitirá determinar qué máquinas de la base instalada son compatibles con Windows 11 y cuáles no.
Las soluciones de gestión de flotas o de gestión de dispositivos móviles, como GLPI y Microsoft Intune, pueden ayudar con esta evaluación, gracias a su funcionalidad de inventario. Para quienes no dispongan de una solución adecuada, ¿cómo proceder?
Microsoft ofrece una herramienta llamada "PC Health Check", pero hay que ejecutarla en cada estación de trabajo manualmente, lo que no es adecuado para un parque informático de decenas, cientos o miles de máquinas. En este artículo, propongo un enfoque basado en la ejecución de un script de PowerShell y la centralización de los resultados en el Directorio Activo.
La idea es sencilla: para cada máquina, indicar si cumple o no los prerrequisitos de Windows 11, dentro del objeto de Active Directory correspondiente. A continuación, se ejecuta un segundo script para generar un informe de auditoría.
II. Uso de PowerShell para determinar la compatibilidad con Windows 11
El script PowerShell necesita comprobar una serie de elementos en la estación de trabajo para determinar si está preparada para Windows 11 o no. En particular, debe examinar detenidamente los siguientes elementos:
- Procesador: 1 GHz o superior con al menos 2 núcleos. Procesador compatible de 64 bits (o ARM).
- Memoria (RAM): 4 GB o más.
- Almacenamiento: 64 GB o más.
- Firmware del sistema: UEFI, compatible con Secure Boot.
- TPM: versión 2.0.
- Tarjeta gráfica: compatible con DirectX 12 o posterior con controlador WDDM 2.0.
Microsoft ofrece un script PowerShell listo para usar que puede ejecutar para averiguar si un equipo es compatible con Windows 11. Puede descargarlo aquí:
Puede ejecutarlo en una máquina, como administrador, para obtener el resultado. La ventaja de este script es que indica el resultado exacto de cada prueba realizada.
.HardwareReadiness.ps1

Nota : HardwareReadiness.ps1 es un script firmado, lo que explica la firma al final del archivo. Sin embargo, ha caducado, ya que el certificado utilizado por Microsoft no es válido desde septiembre de 2022.
B. Adaptar el guión: centralizar los resultados en AD
Este script es una buena base y hace la mayor parte del trabajo. El inconveniente es que devuelve un resultado en la consola, lo que significa que tienes que estar delante de la máquina para leer el resultado. Esto no es lo que queremos.
Nota : este script puede ejecutarse a distancia mediante el protocolo WinRM. Sin embargo, esto requiere que la máquina esté en línea en el momento de la interrogación y, sobre todo, la Gestión remota debe estar habilitada en Windows (que no es la predeterminada en Windows 10).
Vamos a modificar este script PowerShell para que la información se pase al Directorio Activo. Por defecto, cada máquina de Active Directory tiene permisos para modificar los atributos del objeto correspondiente. Vamos a aprovechar esta oportunidad para almacenar los resultados de la prueba en el Directorio Activo.
Nuestro objetivo es ascender en el info
de cada objeto informático. Podríamos elegir otro atributo, pero éste es generalmente libre, a diferencia del description
que se utiliza a menudo.
No vamos a utilizar los comandos del módulo PowerShell de ActiveDirectory, para evitar tener que instalarlo en máquinas remotas. En su lugar, vamos a utilizar componentes nativos soportados por todos los equipos con Windows 10.
Comience por editar el script PowerShell para modificar la línea 490 con el fin de almacenar en una variable $Result
el resultado del comando :
$Result = $outObject | ConvertTo-Json -Compress
A continuación, a continuación de la línea mencionada anteriormente (pero antes de la firma), introduzca este fragmento de código:
$ComputerName = $env:COMPUTERNAME
$ADSearch = New-Object DirectoryServices.DirectorySearcher
$ADSearch.SearchRoot = "LDAP://DC=IT-CONNECT,DC=LOCAL"
$ADSearch.Filter = "(&(objectCategory=Computer)(CN=$ComputerName))"
$ADComputerObj = [ADSI]$ADSearch.FindOne().Path
if($ADComputerObj -ne $null){
$ADComputerObj.Put( "Info", $Result )
$ADComputerObj.SetInfo()
}
He aquí, por orden, el significado de estos mandatos:
- Recuperar el nombre del ordenador local.
- Cree un objeto de búsqueda de Active Directory.
- Defina la raíz LDAP en la que buscar.
- Crear un filtro LDAP para recuperar sólo el objeto correspondiente al ordenador actual.
- Buscar el ordenador con una consulta LDAP.
- Cambiar el valor del atributo del ordenador
Info
(si se ha encontrado el ordenador en la ruta anterior) - Guarde los cambios en Active Directory.
Registraremos esta nueva versión con el nombre ADHardwareReadiness.ps1
.
III. Compatibilidad con Windows 11: un análisis a escala de un parque informático
A. Ejecutar el script PowerShell con un GPO
El script PowerShell se lanzará en los equipos desde una directiva de grupo (GPO). Se lanzará cuando se inicie la máquina Windows. Nos aseguraremos de apuntar sólo a las máquinas que ejecutan Windows 10, gracias a un filtro WMI. Las máquinas que ya ejecutan Windows 11 no se incluirán en nuestro análisis.
Desde la consola de administración de GPO, cree un nuevo filtro WMI. Mediante una consulta, aplicará la GPO únicamente a los equipos con Windows 10, aunque la OU de destino contenga equipos con Windows 11. Este será probablemente tu caso... Al menos, es el mío con la OU PC
a la que se dirigirá (enlace GPO).

Introduzca un nombre y una descripción (1) y, a continuación, haga clic en el botón "Añadir" (2). Introdúzcalo como valor de consulta WMI (3) y, a continuación, confirme (4):
SELECT * FROM Win32_OperatingSystem WHERE Version LIKE "10.%" AND ProductType = 1

Confirmar. Cree un nuevo GPO y empiece asociándolo al filtro WMI creado anteriormente.

A continuación, edite la directiva de grupo para configurarla. Como recordatorio, el script PowerShell debe ejecutarse al iniciar la máquina. Examine la configuración de la siguiente manera:
- Configuración del ordenador > Estrategias > Configuración de Windows > Scripts (inicio/apagado) > Inicio
Cambie a la pestaña "PowerShell" y haga clic en el botón "Añadir".

A continuación, tendrá que copiar y pegar su script PowerShell en el directorio expuesto, o recuperarlo de otro lugar (de Netlogon, por ejemplo).

Tu GPO ya está listo. Todo lo que tienes que hacer es vincularlo a una o más OUs, dependiendo de tus necesidades (¡recuerda probar primero!). Vaya a una máquina Windows 10 para hacer una prueba: ejecute un gpupdate /force
y luego reiniciar. El resto tiene lugar en el AD...
B. Visión general de los resultados en Active Directory
Empezaremos con una comprobación visual. Abra la consola Usuarios y equipos de Active Directory y, a continuación, acceda a las propiedades del objeto equipo correspondiente a la máquina de prueba (recuerde habilitar la visualización de funciones avanzadas antes).
Vaya a la pestaña "Editor de atributos". A continuación, busque el atributo info
en la lista. ¡Se ha actualizado el atributo!

En concreto, tenemos una cadena completa en este atributo de la forma :
{"returnCode":1,"returnReason":"Storage, TPM, ","logging":"Storage: OSDiskSize=63GB. FAIL; Memory: System_Memory=4GB. PASS; TPM: TPMVersion=False. FAIL; Processor: {AddressWidth=64; MaxClockSpeed=3992; NumberOfLogicalCores=2; Manufacturer=AuthenticAMD; Caption=AMD64 Family 25 Model 117 Stepping 2; }. PASS; SecureBoot: Capable. PASS; ","returnResult":"NOT CAPABLE"}
Podríamos ejecutar el siguiente comando para mostrar el nombre y el resultado de la prueba para cada máquina Windows 10 registrada en el AD.
Get-ADComputer -Filter {OperatingSystem -like "Windows 10*"} -Property OperatingSystem, Info | Format-Table Name, Info
El formato de la cadena en el campo info
¿te suena? No, ¿no crees? El formato JSON. Eso es porque utilizamos el formato ConvertTo-Json
al final del script. La buena noticia es que PowerShell puede leer JSON muy bien. Esto es lo que vamos a explotar en la siguiente parte de este artículo, dedicado a la presentación de informes.
C. Compatibilidad con SecureBoot
Cuando realicé varias pruebas con este script, me di cuenta de que la compatibilidad con SecureBoot no siempre era correcta. De hecho, el comando PowerShell Confirm-SecureBootUEFI
no parece apreciar la ejecución como SYSTEM
a través de un GPO.
En consecuencia, obtenemos este tipo de resultado en AD :
{"returnCode":-1,"returnReason":"","logging":"Storage: OSDiskSize=126GB. PASS; Memory: System_Memory=4GB. PASS; TPM: TPMVersion=2.0, 0, 1.16. PASS; Processor: {AddressWidth=64; MaxClockSpeed=3992; NumberOfLogicalCores=2; Manufacturer=AuthenticAMD; Caption=AMD64 Family 25 Model 117 Stepping 2; }. PASS; SecureBoot: Undetermined. UNDETERMINED; UnauthorizedAccessException Impossible de définir les privilèges nécessaires. Accès refusé.; ","returnResult":"UNDETERMINED"}
Es una lástima, ya que este comando tiene la ventaja de devolver un estado preciso : SecureBoot disponible y habilitado, SecureBoot disponible y deshabilitado, y SecureBoot no soportado. Para evitar este problema, el comando ADHardwareReadiness.ps1
se ha modificado para adaptar la prueba SecureBoot a un método basado en el Registro de Windows (a partir de la línea 431).
Se ha integrado el siguiente código en lugar del original (enlace de descarga al final de la página):
# SecureBoot
$SecureBootKey = "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State"
try {
$isSecureBootEnabled = (Get-ItemProperty -Path $SecureBootKey -Name "UEFISecureBootEnabled" -ErrorAction Stop).UEFISecureBootEnabled
if($isSecureBootEnabled -eq 1){
$outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $CAPABLE_STRING, $PASS_STRING
UpdateReturnCode -ReturnCode 0
}else{
UpdateReturnCode -ReturnCode 1
$outObject.returnReason += $logFormatReturnReason -f $SECUREBOOT_STRING
$outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $NOT_CAPABLE_STRING, $FAIL_STRING
$exitCode = 1
}
}
catch {
UpdateReturnCode -ReturnCode -1
$outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
$outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
$exitCode = 1
}
Tras esta modificación, ¡la información fluye ahora correctamente! Ahora podemos pasar a la fase de información.
Nota : ejecutar el comando
Confirm-SecureBootUEFI
a través de PsExec funciona, lo que puede ser una vía que merezca la pena explorar, pero implica ejecutar esta herramienta en las estaciones de trabajo a auditar.
D. Creación de un informe
Por último, utilizando PowerShell, leeremos la información contenida en el atributo info
Windows 10 para generar un informe completo. Muy rápidamente, usted puede :
- Vea el porcentaje de su base instalada que es compatible con Windows 11
- Vea las principales razones por las que se detecta una incompatibilidad
- Obtenga un estado preciso de cada ordenador con la tabla resumen
A continuación figura un resumen del informe.

Este script, que puedes encontrar en nuestra página de GitHub, utiliza el módulo PSWriteHtml para generar el informe HTML. Puede modificarlo para adaptarlo a sus necesidades.
<#
.SYNOPSIS
This script analyzes the “info” attribute of Windows 10 computers in the Active Directory, to generate a Windows 11 compatibility report.
.DESCRIPTION
This script helps you get an overall view of the Windows 11 compatibility of a set of computers, thanks to an HTML report comprising several graphs.
.AUTHOR
Florian Burnel - IT-Connect.fr
.VERSION
1.0 - Initial version.
.NOTES
Filename: Get-ADHardwareReadinessReport.ps1
Creation Date: 2025/02/18
#>
# Get a list of Windows 10 computers in the Active Directory
$ADComputersWin10 = Get-ADComputer -Filter {OperatingSystem -like "Windows 10*"} -Property OperatingSystem, Info | Sort-Object Name
# Get the list of Windows 10 computers and the result of the compatibility test
$ComputersW11Readiness = $ADComputersWin10 | Select-Object Name, @{
Name="Result";
Expression={
$JsonObject = $_.Info | ConvertFrom-Json
if ($JsonObject.returnResult -ne $null){ $JsonObject.returnResult }else{ "EMPTY" }
}
}, @{
Name="Reason";
Expression={
$JsonObject = $_.Info | ConvertFrom-Json
if($JsonObject.returnReason -ne $null){ ($JsonObject.returnReason).TrimEnd(", ") }else{ "" }
}
}
# Counting by status
$ComputersW11ReadinessStats = $ComputersW11Readiness | Group-Object -Property Result | Sort-Object Count -Descending
# Counting occurrences of different reasons
$ReasonCounts = @{}
$ComputersW11Readiness | ForEach-Object {
$Reasons = $_.Reason -split ", "
foreach ($Reason in $Reasons) {
if (-not [string]::IsNullOrWhiteSpace($Reason)) {
if ($ReasonCounts.ContainsKey($Reason)) {
$ReasonCounts[$Reason]++
} else {
$ReasonCounts[$Reason] = 1
}
}
}
}
# HTML report construction with PSWriteHTML
New-HTML -Title "Compatibility of computers with Windows 11" -FilePath "C:\Scripts\HTML\Rapport-Windows-11-Readiness.html" -ShowHTML:$true {
# Report header with domain name and date
New-HTMLHeader {
New-HTMLSection -Invisible {
New-HTMLPanel -Invisible {
New-HTMLText -Text "Domain : $($env:USERDNSDOMAIN)" -FontSize 18 -FontWeight 100
New-HTMLText -Text "Date : $(Get-Date -Format "dd/MM/yyyy")" -FontSize 12
} -AlignContentText left
}
}
# Section 1 - Graphs
New-HTMLSection -HeaderText "Compatibility with Windows 11" -HeaderBackGroundColor "#00698e" {
New-HTMLChart -Title "Compatibility of all IT assets" -Gradient {
foreach ($Line in $ComputersW11ReadinessStats) {
New-ChartDonut -Name $Line.Name -Value $Line.Count
}
}
New-HTMLChart -Title "Reasons for incompatibility" -Gradient {
foreach ($Reason in $ReasonCounts.Keys) {
New-ChartDonut -Name $Reason -Value $ReasonCounts[$Reason]
}
}
}
# Section 2 - Computer list tables
New-HTMLSection -HeaderText "Results of computer compatibility tests" -HeaderBackGroundColor "#00698e" {
New-HTMLPanel {
New-HTMLTable -DataTable $ComputersW11Readiness -HideFooter -AutoSize
}
}
}
IV. Conclusión
Gracias a estos dos scripts, dispones de un método sencillo y eficaz para evaluar la compatibilidad de tus activos informáticos con Windows 11. Basado en un dominio de Active Directory, este método automatiza la auditoría de los equipos, lo que permite comprobar rápidamente si cumplen los criterios exigidos, incluido el TPM (un escollo importante en muchos casos).
Tanto si está planeando una actualización planificada como una migración gradual, estos scripts le ofrecen una visión clara del estado de sus estaciones de trabajo. Le ayudan a preparar su proyecto de migración a Windows 11.
Aquí están los enlaces para descargar los guiones.
- ADHardwareReadiness.ps1 - Para ser ejecutado por GPO

- Get-ADHardwareReadinessReport.ps1 - Para generar el informe

Si tienes alguna pregunta o idea para mejorar estos scripts, no dudes en comentar este artículo o enviar una modificación a GitHub.