PowerShell: qué es, comandos y scripts con ejemplos probados

Ventana de PowerShell 7 en Windows Terminal con el resultado de $PSVersionTable: versión 7.5.5, edición Core

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.

AspectoCMDPowerShell
Qué devuelve una ordenTextoObjetos con propiedades
Nombre de las órdenesCortos, como dir o copyVerbo y sustantivo, como Get-ChildItem
Ejecuta los programas de consolaSíSí: ipconfig, ping o robocopy funcionan igual
Archivos de automatización.bat y .cmd.ps1
Tiempo de arranque que medimos18 ms291 ms la 5.1 y 422 ms la 7
Funciona en Linux y macOSNoSí, 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:\Datos es una carpeta de ejemplo, D:\Informes guarda los resultados y D:\Scripts guarda los scripts. Cámbielas por las suyas.
  • Mayúsculas y minúsculas dan igual: get-process y Get-Process hacen 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 -WhatIf al 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:

  1. Pulse la tecla Windows, escriba powershell y pulse Entrar.
  2. Haga clic derecho en el botón Inicio y elija «Terminal».
  3. Pulse Windows + R, escriba powershell y 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.

DatoWindows PowerShell 5.1PowerShell 7
Cómo llegaViene con WindowsSe instala aparte
Programapowershell.exepwsh.exe
Base.NET Framework 4.8.NET 10, en la 7.6
Recibe funciones nuevasNo, solo correccionesSí
SistemasSolo WindowsWindows, 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ónPublicadaFin del soporte
7.6 (LTS)18 de marzo de 202614 de noviembre de 2028
7.523 de enero de 202510 de noviembre de 2026
7.4 (LTS)16 de noviembre de 202310 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é probamosWindows PowerShell 5.1PowerShell 7.6
Encadenar con &&Error: «no es un separador de instrucciones válido»Funciona
ForEach-Object -ParallelErrorFunciona
Get-UptimeNo existeExiste
curlEs un alias de Invoke-WebRequestEs el programa curl.exe
Texto guardado con >UTF-16, 32 bytes en la pruebaUTF-8, 17 bytes
Primera línea de Export-CsvUna línea #TYPE que estorbaLos nombres de las columnas
Get-WmiObjectExisteEn 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:

VerboQué haceEjemplo
GetConsulta, sin cambiar nadaGet-Process
SetCambia un valorSet-Location
NewCreaNew-Item
RemoveBorraRemove-Item
Start y StopArranca y detieneStop-Process
TestComprueba y responde sí o noTest-Path
Export e ImportGuarda y lee datosExport-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 escribePowerShell ejecuta
dir, lsGet-ChildItem
cdSet-Location
copy, cpCopy-Item
del, rmRemove-Item
type, catGet-Content
clsClear-Host
echoWrite-Output
killStop-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:

OrdenQué haceAlias
Where-ObjectFiltra: deja pasar lo que cumple una condiciónwhere, ?
Select-ObjectElige propiedades o las primeras filasselect
Sort-ObjectOrdenasort
Group-ObjectAgrupa y cuentagroup
Measure-ObjectSuma, promedia y cuentameasure

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:

  • -NoTypeInformation evita que la versión 5.1 escriba una primera línea #TYPE, que Excel muestra como un dato más.
  • -Encoding UTF8 conserva las tildes y la letra ñ.
  • -UseCulture usa 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:

OperadorSignificaEjemplo
-eqIgual$estado -eq 'Running'
-neDistinto$n -ne 0
-gt, -geMayor, mayor o igual$libre -gt 15
-lt, -leMenor, menor o igual$fecha -lt $limite
-likeCoincide con comodines$nombre -like '*.pdf'
-matchCoincide con una expresión regular$linea -match 'error'
-and, -or, -notY, 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.

DirectivaQué permite
RestrictedÓrdenes sueltas, ningún script. Es el valor de fábrica en Windows 10 y 11
RemoteSignedLos scripts creados en el equipo. Los descargados necesitan firma. Es el valor de fábrica en Windows Server
AllSignedSolo scripts con firma digital
BypassTodo, 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 archivoWindows PowerShell 5.1PowerShell 7
UTF-8 sin BOM, como guardan hoy casi todos los editoresTexto roto: 15 caracteres en lugar de 13Correcto
UTF-8 con BOMCorrectoCorrecto

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.

TareaForma lentaForma rápida
Llenar una lista de 50.000 elementos, en la 5.177 s con +=36 ms
La misma lista, en la 7.66,4 s con +=123 ms
Buscar 200 archivos entre 20.000, en la 5.11.010 ms con Where-Object16 ms con -Filter
La misma búsqueda, en la 7.6565 ms con Where-Object11 ms con -Filter
Leer un registro de 200.000 líneas, en la 5.12,7 s131 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:

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-Command ni con Enter-PSSession. Exigen un segundo equipo configurado.
  • No instalamos PowerShell 7 con winget, porque el equipo ya lo tenía. Sí comprobamos que winget ofrecí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 AllSigned solo 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.

Hablemos de la TI de su empresa

Cuéntenos qué necesita su operación y le enviamos una propuesta por escrito. Cada línea del portafolio se contrata por separado.

Compartir este artículo

Últimas entradas

Escríbanos ahora