PowerShell es la consola de Windows para hacer en una línea lo que con el ratón lleva diez minutos. Además, es un lenguaje para guardar esas líneas y repetirlas cuando haga falta. Esta guía explica qué es, cómo se abre y qué comandos conviene conocer. Además, compara PowerShell vs CMD y aclara cuándo hace falta PowerShell 7. También enseña a crear scripts de PowerShell y a resolver el error más buscado: «la ejecución de scripts está deshabilitada en este sistema».
No lo copiamos del manual. Ejecutamos cada orden en un equipo real, con las dos versiones que conviven hoy: PowerShell 7 y Windows PowerShell 5.1. Así encontramos lo que la ayuda no avisa. Por ejemplo, un script que falla puede terminar con el código 0, el de «todo salió bien». Además, una misma lista de 50.000 elementos tardó 77 segundos o 36 milisegundos, según cómo se escribió el bucle.
Si viene del Símbolo del sistema, tenga a mano nuestra guía de comandos CMD. Aquí verá que casi todo lo que sabe sigue sirviendo.
Qué es PowerShell y para qué sirve
PowerShell es tres cosas a la vez: una consola, un lenguaje de scripts y una herramienta para administrar equipos. Microsoft lo publicó en noviembre de 2006. Desde 2016 es de código abierto y funciona también en Linux y en macOS.
Sirve, sobre todo, para cuatro trabajos:
- Consultar el equipo: discos, procesos, servicios, red y actualizaciones.
- Trabajar con muchos archivos a la vez: buscar, copiar, renombrar o limpiar.
- Repetir una tarea sin errores, guardada en un script.
- Administrar plataformas como Windows Server, Active Directory o Microsoft 365.
Para un usuario corriente, basta con saber abrirlo y seguir una instrucción de soporte. En cambio, para quien administra equipos es la herramienta diaria.
PowerShell vs CMD: en qué se diferencian
La pregunta más repetida es si PowerShell es lo mismo que CMD. No lo es. CMD devuelve texto. PowerShell, en cambio, devuelve objetos, es decir, datos con sus propiedades. Por eso se pueden ordenar, filtrar y exportar sin recortar columnas a mano.
| Aspecto | CMD | PowerShell |
|---|---|---|
| Qué devuelve una orden | Texto | Objetos con propiedades |
| Nombre de las órdenes | Cortos, como dir o copy | Verbo y sustantivo, como Get-ChildItem |
| Ejecuta los programas de consola | Sí | Sí: ipconfig, ping o robocopy funcionan igual |
| Archivos de automatización | .bat y .cmd | .ps1 |
| Tiempo de arranque que medimos | 18 ms | 291 ms la 5.1 y 422 ms la 7 |
| Funciona en Linux y macOS | No | Sí, desde la versión 6 |
En resumen, PowerShell vs CMD no es una pelea. CMD arranca antes y sirve para lo sencillo. PowerShell hace lo mismo y mucho más: en nuestro equipo había 1.670 cmdlets en la versión 5.1 y 1.779 en la 7.
Dónde probamos los ejemplos
El equipo de prueba fue un Windows 11 Pro con Windows PowerShell 5.1.26100 y PowerShell 7.6.6. Trabajamos sin permisos de administrador, como un usuario corriente. Así vimos también qué órdenes exigen elevar la consola.
Cada medida de tiempo es la mediana de tres o cinco pasadas. Sin embargo, son cifras de un solo equipo: tómelas como orden de magnitud y no como promesa.
Cómo leer los ejemplos de PowerShell
D:\Datoses una carpeta de ejemplo,D:\Informesguarda los resultados yD:\Scriptsguarda los scripts. Cámbielas por las suyas.- Mayúsculas y minúsculas dan igual:
get-processyGet-Processhacen lo mismo. - La tecla Tab completa nombres y opciones. Úsela: evita casi todos los errores de escritura.
- Antes de borrar o cambiar algo, añada
-WhatIfal final. Con esa opción, la orden solo muestra lo que haría.
Cómo abrir PowerShell en Windows 11
Hay tres formas rápidas:
- Pulse la tecla Windows, escriba
powershelly pulse Entrar. - Haga clic derecho en el botón Inicio y elija «Terminal».
- Pulse Windows + R, escriba
powershelly acepte.
En Windows 11, la consola se abre dentro de Terminal, la ventana con pestañas. Desde la flecha de su barra de título puede abrir otra pestaña con CMD o con otra versión. En Windows 10 sirven la primera forma y la tercera.
Cómo abrir PowerShell como administrador
Algunas órdenes cambian el sistema y piden permisos. Para eso, haga clic derecho en Inicio y elija «Terminal (Administrador)». Windows preguntará si permite los cambios.
Lo comprobamos por las malas. Sin elevar, cambiar una configuración del equipo respondió «Se denegó el acceso a la clave de Registro». El propio mensaje recomienda abrir la consola con la opción «Ejecutar como administrador».
Aun así, no trabaje siempre elevado. Una orden mal escrita hace mucho más daño con permisos de administrador.
Cómo saber qué versión de PowerShell tiene
Escriba esta línea. La respuesta empieza por 5.1 o por 7:
$PSVersionTable.PSVersion
PowerShell 7 y Windows PowerShell 5.1: cuál usar
Hoy conviven dos productos con casi el mismo nombre. Conviene distinguirlos, porque muchos errores vienen de confundirlos.
| Dato | Windows PowerShell 5.1 | PowerShell 7 |
|---|---|---|
| Cómo llega | Viene con Windows | Se instala aparte |
| Programa | powershell.exe | pwsh.exe |
| Base | .NET Framework 4.8 | .NET 10, en la 7.6 |
| Recibe funciones nuevas | No, solo correcciones | Sí |
| Sistemas | Solo Windows | Windows, Linux y macOS |
PowerShell 7 no reemplaza a la 5.1. Se instala en otra carpeta y las dos funcionan a la vez. Por tanto, instalarlo no rompe los scripts que ya tenga.
Nuestra recomendación es sencilla. Para seguir una instrucción de soporte, la 5.1 que trae Windows basta. En cambio, para escribir scripts nuevos conviene PowerShell 7.
Cómo instalar PowerShell 7
La forma más corta usa winget, que viene con Windows 11:
winget install --id Microsoft.PowerShell --source winget
También está en Microsoft Store y como instalador MSI. Según la guía de instalación de Microsoft, el MSI es la mejor opción para servidores y despliegues de empresa.
Hay una razón práctica. Según esa misma guía, la versión de la Tienda se instala para un solo usuario, no admite la administración remota y no deja cambiar la configuración que vale para todo el equipo.
Cuánto dura el soporte de cada versión
Microsoft publica una versión nueva de PowerShell 7 cada año, más o menos. Unas son de soporte largo (LTS) y otras duran menos. Estas son las fechas de su página de ciclo de vida:
| Versión | Publicada | Fin del soporte |
|---|---|---|
| 7.6 (LTS) | 18 de marzo de 2026 | 14 de noviembre de 2028 |
| 7.5 | 23 de enero de 2025 | 10 de noviembre de 2026 |
| 7.4 (LTS) | 16 de noviembre de 2023 | 10 de noviembre de 2026 |
Por tanto, quien tenga la 7.4 o la 7.5 debe pasar a la 7.6 antes del 10 de noviembre de 2026. Además, Microsoft solo da soporte a la última actualización de cada versión. Desde su salida, la 7.6 recibió seis actualizaciones en seis meses.
Windows PowerShell 5.1, en cambio, sigue el ciclo de Windows. Mientras su Windows tenga soporte, la 5.1 también.
Qué cambia entre PowerShell 7 y la 5.1
Comprobamos estas diferencias una por una, con la misma orden en las dos versiones:
| Qué probamos | Windows PowerShell 5.1 | PowerShell 7.6 |
|---|---|---|
Encadenar con && | Error: «no es un separador de instrucciones válido» | Funciona |
ForEach-Object -Parallel | Error | Funciona |
Get-Uptime | No existe | Existe |
curl | Es un alias de Invoke-WebRequest | Es el programa curl.exe |
Texto guardado con > | UTF-16, 32 bytes en la prueba | UTF-8, 17 bytes |
Primera línea de Export-Csv | Una línea #TYPE que estorba | Los nombres de las columnas |
Get-WmiObject | Existe | En nuestro equipo siguió respondiendo |
La última fila merece una nota. Microsoft indica que Get-WmiObject se retiró de PowerShell 7. Sin embargo, en nuestro Windows respondió: la versión 7 puede cargar módulos de la 5.1 en modo de compatibilidad. Para scripts nuevos use Get-CimInstance, que funciona en las dos.
Comandos de PowerShell: cómo se leen
Las órdenes propias se llaman cmdlets. Todas siguen la misma regla: un verbo, un guion y un sustantivo. Por ejemplo, Get-Service obtiene servicios y Stop-Service los detiene.
Esa regla ahorra memoria. Si conoce el verbo, adivina la orden. Estos son los más usados:
| Verbo | Qué hace | Ejemplo |
|---|---|---|
Get | Consulta, sin cambiar nada | Get-Process |
Set | Cambia un valor | Set-Location |
New | Crea | New-Item |
Remove | Borra | Remove-Item |
Start y Stop | Arranca y detiene | Stop-Process |
Test | Comprueba y responde sí o no | Test-Path |
Export e Import | Guarda y lee datos | Export-Csv |
En nuestro equipo, el verbo Get encabeza más de 5.000 órdenes, contando las funciones de los módulos. Por eso casi todo lo que empieza por Get es seguro: solo mira.
Tres órdenes para no memorizar nada
Nadie recuerda mil nombres. En su lugar, se aprenden tres órdenes que enseñan las demás:
Get-Command -Noun Service
Get-Help Get-Service -Examples
Get-Service | Get-Member
La primera busca órdenes por su sustantivo. En la prueba devolvió ocho en la versión 5.1 y nueve en la 7, desde Get-Service hasta Suspend-Service. La segunda muestra ejemplos de uso. La tercera, por último, lista las propiedades de lo que devuelve una orden.
La ayuda viene resumida de fábrica. Para descargarla completa existe Update-Help, que en la versión 5.1 exige una consola de administrador.
Los alias: por qué funcionan dir, cd y ls
PowerShell acepta los nombres de CMD y de Linux mediante alias. Así, quien llega de otra consola no empieza de cero.
| Usted escribe | PowerShell ejecuta |
|---|---|
dir, ls | Get-ChildItem |
cd | Set-Location |
copy, cp | Copy-Item |
del, rm | Remove-Item |
type, cat | Get-Content |
cls | Clear-Host |
echo | Write-Output |
kill | Stop-Process |
Sin embargo, el alias solo presta el nombre. Las opciones son las de PowerShell. Por eso dir /s no funciona aquí: el equivalente es dir -Recurse.
Un consejo: use alias al escribir en la consola y nombres completos en los scripts. Un script con nombres completos se entiende dentro de un año.
Los comandos esenciales para el día a día
Con una veintena de órdenes se resuelve casi todo el trabajo diario. Las agrupamos en tres bloques: archivos, sistema y red. Ninguna de las que siguen cambia nada, salvo Copy-Item.
Archivos y carpetas
Get-ChildItem D:\Datos -Recurse -Filter *.pdf
Copy-Item D:\Datos\informe.pdf D:\Informes
Get-Content D:\Datos\registro.log -Tail 20
Select-String -Path D:\Datos\*.log -Pattern 'error'
La primera línea busca todos los PDF de una carpeta y de sus subcarpetas. La segunda copia un archivo. La tercera muestra las últimas 20 líneas de un registro. La cuarta, por último, busca una palabra dentro de varios archivos, como hace findstr en CMD.
Para copiar carpetas enteras hay una herramienta mejor. La explicamos en la guía de Robocopy, que también funciona desde esta consola.
Sistema: procesos, servicios, discos y actualizaciones
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 5 Name, Id
Get-Service | Where-Object Status -eq 'Running'
Get-CimInstance Win32_LogicalDisk -Filter 'DriveType=3' | Select-Object DeviceID, FreeSpace, Size
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 5
La primera línea muestra los cinco procesos que más memoria ocupan. Es lo mismo que enseña el Administrador de tareas, pero se puede guardar en un archivo. Las otras tres listan los servicios en marcha, el espacio de cada disco y las últimas actualizaciones.
En nuestro equipo había 532 procesos y 313 servicios, de los que 143 estaban en ejecución. Buscar a ojo entre tantos no es práctico. Filtrar, en cambio, lleva una línea.
Otro dato útil es cuánto lleva encendido el equipo. En PowerShell 7 basta con Get-Uptime. En la versión 5.1 esa orden no existe y se calcula así:
(Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
Red: comprobar una conexión
Test-NetConnection www.kharonte.com -Port 443
Resolve-DnsName www.kharonte.com
Get-NetIPAddress -AddressFamily IPv4
La primera orden une ping y la prueba de un puerto. Si responde TcpTestSucceeded : True, el servicio contesta. Las otras dos consultan el DNS y muestran las direcciones del equipo, como nslookup e ipconfig.
Un aviso medido: contra un puerto abierto, la prueba tardó entre 3 y 6 segundos. Contra un puerto que no responde, en cambio, tardó 43 segundos. Por tanto, si la consola parece colgada, espere: no lo está.
Los programas de siempre también valen. Por ejemplo, ipconfig /all funciona igual. Además, su salida se puede filtrar:
ipconfig /all | Select-String 'IPv4'
La tubería de PowerShell: objetos, no texto
La barra vertical une órdenes: lo que sale de una entra en la siguiente. Se llama tubería. En CMD y en Linux, por la tubería viaja texto. En PowerShell viajan objetos, y esa es la diferencia que más trabajo ahorra.
Lo comprobamos. Un proceso llega con casi 70 propiedades: nombre, memoria, hora de inicio y más. En cambio, cada línea de ipconfig llega como texto simple, sin propiedades que filtrar.
Estas cinco órdenes hacen casi todo el trabajo dentro de una tubería:
| Orden | Qué hace | Alias |
|---|---|---|
Where-Object | Filtra: deja pasar lo que cumple una condición | where, ? |
Select-Object | Elige propiedades o las primeras filas | select |
Sort-Object | Ordena | sort |
Group-Object | Agrupa y cuenta | group |
Measure-Object | Suma, promedia y cuenta | measure |
Un ejemplo: cuántos archivos hay de cada tipo
Get-ChildItem D:\Datos -Recurse -File |
Group-Object Extension |
Sort-Object Count -Descending |
Select-Object Name, Count
La orden lista los archivos, los agrupa por extensión, ordena los grupos y deja dos columnas. Una línea puede terminar en la barra vertical y seguir en la siguiente. Así se lee mejor.
Para saber cuánto ocupan, cambie el final:
Get-ChildItem D:\Datos -Recurse -File | Measure-Object Length -Sum
Cómo exportar el resultado a Excel o a JSON
Como son objetos, pasarlos a un archivo de datos lleva una orden más:
Get-Service | Select-Object Name, Status, StartType |
Export-Csv D:\Informes\servicios.csv -NoTypeInformation -Encoding UTF8 -UseCulture
Las tres opciones tienen su motivo, y las tres las probamos:
-NoTypeInformationevita que la versión 5.1 escriba una primera línea#TYPE, que Excel muestra como un dato más.-Encoding UTF8conserva las tildes y la letra ñ.-UseCultureusa el separador de la configuración regional de Windows, que es el que espera Excel en ese equipo. En el nuestro, configurado en español de México, fue la coma. En otros países es el punto y coma.
Para otros programas sirve JSON:
Get-Service | Select-Object Name, Status | ConvertTo-Json | Out-File D:\Informes\servicios.json
Probar antes de borrar con -WhatIf
Casi todas las órdenes que cambian algo aceptan -WhatIf. Con esa opción no hacen nada: solo dicen lo que harían.
Remove-Item D:\Datos\*.tmp -WhatIf
En la prueba respondió con una línea por archivo, que nombra la operación «Quitar archivo» y su ruta. Los archivos siguieron en su sitio. Por eso es la costumbre más barata que hay antes de un borrado.
Variables, comparaciones y comillas
Una variable guarda un valor para usarlo después. Su nombre empieza siempre por el signo de dólar.
$carpeta = 'D:\Datos'
$limite = (Get-Date).AddDays(-30)
Get-ChildItem $carpeta -File | Where-Object LastWriteTime -lt $limite
El ejemplo lista los archivos que nadie modificó en los últimos 30 días. La segunda línea calcula la fecha límite. La tercera, a su vez, compara cada archivo con ella.
Los operadores de comparación
Aquí está la mayor sorpresa para quien viene de otros lenguajes. PowerShell no compara con símbolos, sino con palabras cortas:
| Operador | Significa | Ejemplo |
|---|---|---|
-eq | Igual | $estado -eq 'Running' |
-ne | Distinto | $n -ne 0 |
-gt, -ge | Mayor, mayor o igual | $libre -gt 15 |
-lt, -le | Menor, menor o igual | $fecha -lt $limite |
-like | Coincide con comodines | $nombre -like '*.pdf' |
-match | Coincide con una expresión regular | $linea -match 'error' |
-and, -or, -not | Y, o, no | $a -gt 1 -and $b -lt 9 |
Además, las comparaciones de texto no distinguen mayúsculas. Si necesita distinguirlas, añada una c al operador. Lo probamos con estas cuatro líneas:
'ABC' -eq 'abc'
'ABC' -ceq 'abc'
'10' -gt '9'
10 -gt '9'
Las respuestas fueron True, False, False y True. La tercera engaña: entre comillas, «10» y «9» son texto, y como texto el 1 va antes que el 9. En cambio, con un número a la izquierda, PowerShell convierte el otro valor y compara bien.
Comillas dobles y comillas simples
$nombre = 'Ana'
"Hola, $nombre"
'Hola, $nombre'
La segunda línea escribe «Hola, Ana». La tercera, en cambio, escribe «Hola, $nombre», tal cual. Dentro de comillas dobles, las variables se sustituyen por su valor. Dentro de comillas simples, no. Por eso las rutas y los textos fijos van mejor entre comillas simples.
Scripts de PowerShell: cómo crear y ejecutar el primero
Un script es un archivo de texto con órdenes, guardado con la extensión .ps1. Sirve para repetir un trabajo sin volver a escribirlo.
Este ejemplo avisa de los discos con poco espacio. Cópielo en el Bloc de notas y guárdelo como D:\Scripts\espacio.ps1:
param(
[int]$Minimo = 15
)
Get-CimInstance Win32_LogicalDisk -Filter 'DriveType=3' | ForEach-Object {
$libre = [int](100 * $_.FreeSpace / $_.Size)
[pscustomobject]@{
Unidad = $_.DeviceID
LibrePct = $libre
Estado = if ($libre -lt $Minimo) { 'BAJO' } else { 'Bien' }
}
}
El bloque param define una opción, -Minimo, con 15 como valor de fábrica. Después, el script recorre los discos, calcula el porcentaje libre y devuelve un objeto por disco. Como devuelve objetos, su resultado también se puede ordenar o exportar.
Cómo ejecutar un script de PowerShell
cd D:\Scripts
.\espacio.ps1
.\espacio.ps1 -Minimo 30
El punto y la barra del principio son obligatorios. Sin ellos, la consola responde que el término «no se reconoce como nombre de un cmdlet». Es una medida de seguridad: PowerShell no ejecuta un archivo de la carpeta actual si no se le indica la ruta.
En nuestro equipo, el disco C: tenía un 21 % libre. Con el valor de fábrica salió «Bien». Con -Minimo 30, en cambio, salió «BAJO».
Por qué un script muestra columnas vacías
Hay una sorpresa al pasar de la consola al script. Si un script lanza varias consultas distintas seguidas, PowerShell usa para todas las columnas de la primera. Lo vimos con el bloque de procesos, servicios y discos. Escritas una a una, cada orden mostró su tabla. Dentro de un script, en cambio, los servicios salieron con la columna Id vacía y los discos no mostraron ningún dato.
El arreglo es terminar cada consulta con | Out-Host. Así, cada una se dibuja por separado.
Con qué programa escribir los scripts de PowerShell
El Bloc de notas sirve para empezar. Sin embargo, para trabajar a diario Microsoft recomienda Visual Studio Code con su extensión para este lenguaje. El editor ISE, que trae Windows, sigue funcionando. Aun así, ya no recibe funciones nuevas y solo trabaja con la versión 5.1.
«La ejecución de scripts está deshabilitada en este sistema»
Es el error que más se busca, y casi todos lo ven la primera vez. Al lanzar un script, la consola responde algo así:
No se puede cargar el archivo D:\Scripts\espacio.ps1 porque la ejecución de scripts está deshabilitada en este sistema.
No es una avería. Es la directiva de ejecución, una regla que decide qué scripts pueden correr. En un Windows de escritorio recién instalado, su valor es Restricted: se pueden escribir órdenes, pero no lanzar archivos.
| Directiva | Qué permite |
|---|---|
Restricted | Órdenes sueltas, ningún script. Es el valor de fábrica en Windows 10 y 11 |
RemoteSigned | Los scripts creados en el equipo. Los descargados necesitan firma. Es el valor de fábrica en Windows Server |
AllSigned | Solo scripts con firma digital |
Bypass | Todo, sin avisos |
Cómo habilitar la ejecución de scripts
Primero mire qué tiene hoy:
Get-ExecutionPolicy -List
La lista muestra cinco ámbitos. Los dos primeros los fija la empresa mediante directivas de grupo, y mandan sobre el resto. Después vienen la ventana actual, el usuario y el equipo.
Para permitir sus propios scripts, la opción recomendada es esta. No pide permisos de administrador, porque solo cambia su usuario:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Si solo quiere probar algo una vez, cambie la directiva de la ventana abierta. Al cerrarla, todo vuelve a como estaba:
Set-ExecutionPolicy RemoteSigned -Scope Process
En cambio, cambiar la directiva de todo el equipo sí exige una consola de administrador. Sin ella, la orden nos respondió «Se denegó el acceso a la clave de Registro».
Un detalle que confunde: cada versión guarda su propia directiva. En nuestro equipo, el usuario tenía RemoteSigned en PowerShell 7 y nada definido en la 5.1. Por tanto, habilitar la ejecución de scripts en una no la habilita en la otra.
El script descargado que sigue sin funcionar
Con RemoteSigned, un script que usted escribió funciona. Sin embargo, el mismo archivo bajado de internet o recibido por correo no arranca. Windows lo marca al descargarlo, y la consola responde que «no está firmado digitalmente».
Lo reprodujimos poniendo esa marca a nuestro script. Dejó de funcionar en las dos versiones. Después de esta orden, volvió a correr:
Unblock-File D:\Scripts\espacio.ps1
Antes de desbloquear un archivo, ábralo y léalo. Si no entiende lo que hace, no lo ejecute.
La directiva de ejecución no es una barrera de seguridad
Aquí hay un malentendido frecuente. La directiva evita errores, pero no detiene a nadie con malas intenciones. La documentación de Microsoft lo dice sin rodeos: no es una frontera de seguridad, y cualquiera puede saltarla escribiendo el contenido del script en la consola.
Lo comprobamos. Con la directiva en Restricted, el archivo no se pudo lanzar. En cambio, su contenido pasado como texto se ejecutó sin ningún aviso, en las dos versiones.
Por eso merece una advertencia la moda de pegar líneas que empiezan por irm y terminan en iex. Circulan mucho, sobre todo para «activar» Windows u Office. La primera parte descarga un script de internet. La segunda lo ejecuta en memoria, sin guardarlo. Ninguna directiva lo frena y, además, nadie llega a leer lo que corre. Si la consola está elevada, ese texto desconocido manda sobre todo el equipo.
Cinco trampas de PowerShell que medimos
Ninguna da un mensaje de error claro. Por eso cuestan horas la primera vez.
El signo > no significa «mayor que»
$libres = 7
if ($libres > 5) { 'Hay espacio' }
if ($libres -gt 5) { 'Hay espacio' }
La segunda línea no escribe nada. Además, deja en la carpeta un archivo llamado 5. El signo > no compara: envía la salida a un archivo, igual que en CMD. La tercera línea es la correcta y sí responde «Hay espacio».
Un solo resultado no es una lista
Supongamos un archivo equipos.txt con un nombre por línea. Con dos nombres, $equipos[0] devuelve el primero. Sin embargo, con un solo nombre devuelve su primera letra. En la prueba, de «servidor01» salió una «s».
La causa es sencilla. Con un único resultado, PowerShell entrega el objeto suelto y no una lista. El arreglo consiste en envolver la orden con @():
$equipos = @(Get-Content D:\Datos\equipos.txt)
$equipos[0]
Las tildes que se rompen en un script
Guardamos el mismo script, con una ñ y una tilde, de dos maneras. Después lo ejecutamos con las dos versiones:
| Cómo se guardó el archivo | Windows PowerShell 5.1 | PowerShell 7 |
|---|---|---|
| UTF-8 sin BOM, como guardan hoy casi todos los editores | Texto roto: 15 caracteres en lugar de 13 | Correcto |
| UTF-8 con BOM | Correcto | Correcto |
Es decir, la versión 5.1 lee un archivo sin esa marca inicial como si fuera de otra codificación. Así, «año» se convierte en «año». Por tanto, si un script con tildes va a correr en la 5.1, guárdelo como «UTF-8 con BOM».
Al escribir archivos pasa algo parecido. En la 5.1, el signo > y Out-File guardan en UTF-16, que ocupa el doble y que otros programas no siempre leen. Para evitarlo, indique la codificación:
'año' | Out-File D:\Informes\prueba.txt -Encoding utf8
El script que falla y termina con el código 0
Esta fue la sorpresa mayor. Lanzamos un script cuya primera orden fallaba, porque buscaba una carpeta que no existía. Mostró el error en rojo, siguió con la orden siguiente y terminó con el código de salida 0.
Para el Programador de tareas, un 0 significa «todo salió bien». Por tanto, una tarea nocturna puede fallar cada noche y aparecer como correcta.
El arreglo son dos piezas. La primera línea convierte cualquier error en una parada. El bloque try y catch, por su parte, anota lo ocurrido y devuelve un código distinto de cero:
$ErrorActionPreference = 'Stop'
try {
$limite = (Get-Date).AddDays(-30)
Get-ChildItem D:\Datos\Temporales -File |
Where-Object LastWriteTime -lt $limite |
Remove-Item
exit 0
}
catch {
Add-Content D:\Informes\limpiar.log "$(Get-Date -Format s) $($_.Exception.Message)"
exit 1
}
El ejemplo borra los archivos de una carpeta temporal con más de 30 días. Guárdelo como D:\Scripts\limpiar.ps1. Lo probamos de las dos maneras. Con la carpeta en su sitio, borró lo antiguo y devolvió 0. Sin la carpeta, en cambio, escribió el motivo en el registro y devolvió 1.
Encadenar con && solo funciona en PowerShell 7
Test-Path D:\Datos && Get-ChildItem D:\Datos
En PowerShell 7, la segunda orden corre solo si la primera termina bien. En la versión 5.1, la misma línea ni siquiera arranca: el analizador responde que && «no es un separador de instrucciones válido en esta versión».
Rendimiento: tres costumbres que cambian los tiempos
Los scripts lentos casi nunca lo son por el equipo. Lo son por cómo están escritos. Medimos tres casos habituales, con las dos versiones.
| Tarea | Forma lenta | Forma rápida |
|---|---|---|
| Llenar una lista de 50.000 elementos, en la 5.1 | 77 s con += | 36 ms |
| La misma lista, en la 7.6 | 6,4 s con += | 123 ms |
| Buscar 200 archivos entre 20.000, en la 5.1 | 1.010 ms con Where-Object | 16 ms con -Filter |
| La misma búsqueda, en la 7.6 | 565 ms con Where-Object | 11 ms con -Filter |
| Leer un registro de 200.000 líneas, en la 5.1 | 2,7 s | 131 ms con -ReadCount 0 |
No llene listas con +=
La forma lenta añade un elemento en cada vuelta con $lista += $n. Cada vez, PowerShell copia la lista entera. La forma rápida, en cambio, recoge directamente lo que devuelve el bucle:
$lista = foreach ($n in 1..50000) { $n }
En la versión 5.1, la diferencia fue de 77 segundos a 36 milisegundos. PowerShell 7 mejoró mucho ese caso, pero la forma rápida sigue ganando por 50 veces.
Filtre en el origen
Get-ChildItem -Filter *.log pide al disco solo lo que busca. En cambio, traerlo todo y filtrar después con Where-Object obliga a crear 20.000 objetos para quedarse con 200. Lo mismo vale para Active Directory o para los registros de eventos: cuanto antes se filtra, menos se espera.
Lea los archivos grandes de una vez
Get-Content entrega el archivo línea a línea, y eso es lento. Para un registro de 10,8 MB tardó 2,7 segundos. Con -ReadCount 0, que lo entrega de golpe, tardó 131 milisegundos. Además, para ver solo el final, -Tail 10 respondió en 1 milisegundo.
Varias tareas a la vez con -Parallel
PowerShell 7 puede repartir un trabajo en varios hilos. Sirve cuando cada elemento espera a algo externo, como un equipo que tarda en contestar.
'servidor01', 'servidor02', 'servidor03' | ForEach-Object -Parallel {
"$_ responde: $(Test-Connection $_ -Count 1 -Quiet)"
}
Lo medimos con diez tareas de medio segundo. Una tras otra tardaron 5,1 segundos. En paralelo, 1,2 segundos, porque de fábrica corren cinco a la vez. Con -ThrottleLimit 10, por último, bajaron a 0,7 segundos.
Cómo programar un script de PowerShell
Para que un script corra solo se usa el Programador de tareas de Windows. La línea completa es esta. En el Programador, powershell.exe va en el campo del programa y el resto va en los argumentos. Para la versión 7, el programa es pwsh.exe.
powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File D:\Scripts\limpiar.ps1
Cada opción evita un problema. -NoProfile impide que la configuración personal cambie el resultado. -ExecutionPolicy fija la directiva solo para esa ejecución, sin tocar la del equipo. -File, por último, hace que el código de salida del script llegue al Programador.
Lo comprobamos con un script que termina en exit 3: la consola devolvió un 3. Así, el Programador distingue un fallo de un éxito. Recuerde, eso sí, la trampa anterior: sin try y catch, el fallo no se ve.
Otro aviso sale de nuestra guía de Robocopy, que programa una copia paso a paso. Una tarea creada con las opciones de fábrica no arranca con el portátil en batería. Allí está el arreglo.
Historial, perfil y transcripción
El historial de PowerShell guarda lo que usted escribe
La flecha hacia arriba recupera órdenes anteriores, incluso de otros días. Esto es posible porque la consola las guarda en un archivo de texto. Para saber dónde está, escriba:
(Get-PSReadLineOption).HistorySavePath
En nuestro equipo, ese archivo tenía 371 líneas y lo comparten las dos versiones. Guarda hasta 4.096 órdenes. Por tanto, conviene saber que existe: una contraseña escrita en una orden puede quedar ahí, en texto claro.
Según la documentación, la consola no guarda las líneas que contienen palabras como password, token o secret. Sin embargo, una clave escrita sin esas palabras sí queda guardada. La norma, pues, es no escribir contraseñas en una orden.
El perfil: su configuración al abrir la consola
El perfil es un script que corre cada vez que se abre la consola. Sirve para definir alias propios o cambiar el aspecto. De fábrica no existe. Estas dos líneas dicen dónde iría y si ya lo tiene:
$PROFILE
Test-Path $PROFILE
Cada versión usa su carpeta. En nuestro equipo, la 5.1 lo busca en Documentos\WindowsPowerShell y la 7 en Documentos\PowerShell. Además, como el perfil es un script, con la directiva Restricted no se carga.
Guardar todo lo que pasa en una sesión
Para documentar un trabajo o adjuntarlo a un caso de soporte, grabe la sesión:
Start-Transcript D:\Informes\sesion.txt
Get-Date
Stop-Transcript
El archivo recoge cada orden y su respuesta, con la fecha, el usuario y el equipo en la cabecera.
PowerShell para administrar servidores y Microsoft 365
Todo lo anterior vale para un solo equipo. Sin embargo, el uso profesional empieza cuando se instalan módulos, que añaden órdenes para un producto concreto. En nuestro equipo había 136 módulos disponibles en la versión 5.1.
En estas guías usamos varios, con sus órdenes probadas:
- Hyper-V: crear y administrar máquinas virtuales.
- Active Directory: usuarios, grupos y equipos de un dominio.
- Visor de eventos: leer los registros de Windows con
Get-WinEvent. - Centro de administración de Microsoft 365: lo que el portal no deja hacer en bloque.
Además, PowerShell puede ejecutar órdenes en otros equipos con Invoke-Command y Enter-PSSession. Para ello, el equipo de destino debe tener habilitada la administración remota. Quien administre servidores Linux encontrará el equivalente en nuestra guía de comandos avanzados de Linux.
Lo que no probamos
Una guía honesta dice dónde termina su laboratorio:
- No ejecutamos órdenes remotas con
Invoke-Commandni conEnter-PSSession. Exigen un segundo equipo configurado. - No instalamos PowerShell 7 con
winget, porque el equipo ya lo tenía. Sí comprobamos quewingetofrecía la versión 7.6.6. - No cambiamos la directiva del usuario ni la del equipo. La probamos por ejecución y en la ventana, que no deja rastro.
- No probamos PowerShell en Linux ni en macOS. Lo que decimos de esos sistemas sale de la documentación de Microsoft.
- No firmamos scripts. La directiva
AllSignedsolo la vimos rechazar un archivo sin firma.
Cuándo conviene dejarlo en manos de un equipo de soporte
PowerShell resuelve un equipo en un minuto. Sin embargo, una empresa tiene decenas, y ahí cambian las preguntas. ¿Quién revisa que el script de anoche funcionó? ¿Quién lo actualiza cuando cambia la versión? ¿Dónde queda escrito lo que se hizo?
En KHARONTE, ese trabajo pasa por una mesa de ayuda TI con cada caso registrado. Nuestro soporte técnico para empresas cubre los puestos de trabajo: diagnóstico, mantenimiento y atención remota o en sitio. Lo que se repite en muchos equipos se automatiza y se documenta, para que no dependa de una sola persona.
Si además quiere delegar servidores, redes y plataformas, eso entra en nuestros servicios administrados de TI. Puede ver el alcance completo en la página de servicios de TI para empresas.
Preguntas frecuentes sobre PowerShell
¿PowerShell es lo mismo que CMD?
No. CMD es el intérprete clásico y devuelve texto. PowerShell es más reciente, devuelve objetos y además ejecuta casi todas las órdenes de CMD.
¿PowerShell es un lenguaje de programación?
Sí, es un lenguaje de scripts completo, con variables, bucles, funciones y manejo de errores. Aun así, no hace falta programar para usarlo como consola.
¿PowerShell es un virus?
No. Es un componente de Windows. Sin embargo, algunos programas maliciosos lo usan para ejecutarse. Si ve ventanas azules o negras que se abren y se cierran solas, pida que revisen el equipo.
¿Hay que desinstalar Windows PowerShell 5.1 para usar PowerShell 7?
No. Las dos versiones conviven. Además, la 5.1 es un componente de Windows y algunos módulos solo funcionan en ella.
¿Cómo sé qué versión de PowerShell tengo?
Escriba $PSVersionTable.PSVersion y pulse Entrar. La respuesta empieza por 5.1 en la versión que trae Windows y por 7 en la moderna.
¿Es seguro cambiar la directiva de ejecución?
RemoteSigned para su usuario es un cambio razonable y es el valor de fábrica de Windows Server. En cambio, evite Bypass y Unrestricted como valor permanente.
¿PowerShell funciona en Mac y en Linux?
Sí. PowerShell 7 se instala en macOS y en las distribuciones principales de Linux. Windows PowerShell 5.1, en cambio, solo existe en Windows.
¿Los comandos de CMD funcionan en PowerShell?
Los programas, como ipconfig, ping o robocopy, funcionan igual. Las órdenes internas de CMD, como dir o copy, funcionan mediante alias, pero con las opciones de PowerShell.




