A las 02:13, un servidor de archivos está “lento”, un equipo de aplicaciones está “bloqueado” y estás frente a una máquina Windows que parece caminar en melaza. Abres una consola, escribes algo sencillo por inercia, y funciona—o no, porque elegiste la shell equivocada para el momento.
Esto no es una guerra religiosa. Es selección de herramientas bajo presión. PowerShell es el caballo de batalla moderno. CMD es la cucaracha de la administración de Windows: molesta de persistente, difícil de matar y todavía en las paredes cuando se apagan las luces.
La diferencia real: objetos vs texto (y por qué le importa a la gente de ops)
CMD es una tubería de texto. PowerShell es una canalización de objetos. Ese es el titular, pero las consecuencias operativas son donde sube la presión arterial.
Contrato de CMD: cadenas hasta el final
En CMD, casi todo lo que haces es “ejecutar un programa, obtener texto, parsear texto, esperar que el texto no cambie”. Algunas utilidades son integradas (como dir), otras son EXE clásicas (como ipconfig), y un número deprimente “imprime lo que imprime”. Eso es limitación y superpoder a la vez: el texto es universal, y CMD está presente incluso cuando la máquina está medio rota.
Contrato de PowerShell: datos estructurados, luego formato
PowerShell empuja objetos .NET, no cadenas, por la canalización. Los cmdlets emiten objetos con propiedades; el formateo ocurre al final. Eso significa que puedes filtrar con fiabilidad (Where-Object), seleccionar campos con precisión (Select-Object) y exportar limpiamente (ConvertTo-Json, Export-Csv). Dejas de escribir regex para encontrar “el tercer token después de los dos puntos”. Dejas de temer la localización, cambios de espacios y anchos de columna.
Pero el modelo de objetos de PowerShell tiene un costo: tiempo de arranque, carga de módulos, scripts de perfil, restricciones de política y, ocasionalmente, el tipo de fallo donde la shell está bien pero falta un módulo y tu comando “simple” se convierte en una caza de dependencias.
Realidad en ops: elige la shell que coincida con tu dominio de fallo
- Si estás en modo de recuperación, con UI limitada o un entorno mínimo: CMD a menudo funciona cuando PowerShell está ausente o incapacitado.
- Si necesitas corrección a escala, orquestación remota, inventario o algo repetible: PowerShell es la apuesta más segura.
- Si haces triage interactivo rápido: cualquiera puede servir, pero elige la que reduzca la carga cognitiva para esa máquina.
Una idea parafraseada (no literal) del coautor de Google SRE Niall Murphy: la confiabilidad viene de diseñar sistemas que fallen de formas previsibles que has ensayado
. La elección de shell es parte de ese ensayo.
Cuándo CMD todavía gana
1) WinRE, Modo Seguro y “no puedo cargar mis juguetes bonitos”
Cuando Windows está en un entorno de recuperación, quieres la menor superficie posible. CMD está disponible en más sitios, con menos piezas móviles. Si la máquina no arranca, no estás para admirar canalizaciones de objetos; estás para hacerla arrancar.
2) Necesitas las utilidades clásicas exactamente como son
Muchas herramientas de diagnóstico de Windows siguen siendo EXE clásicas: wevtutil, netsh, sc, robocopy, diskpart, bcdedit. PowerShell también puede llamarlas, pero las reglas de comillas de CMD suelen coincidir con los ejemplos que encontrarás en runbooks y documentos de incidentes antiguos.
3) El tiempo de arranque importa (sí, a veces importa)
CMD se abre rápido, incluso en un host estresado. PowerShell también puede ser rápido, pero los módulos, perfiles y controles empresariales a veces lo hacen lento. Cuando estás iterando rápido—prueba un cambio, vuelve a ejecutar una comprobación—la latencia importa.
4) Los archivos por lotes siguen por todas partes (y algunos son críticos)
Si tu organización tiene pegamento de despliegue de 15 años, probablemente sea un archivo .bat o .cmd que usa if errorlevel y algún parsing frágil. Reescribirlo a veces es sensato, pero no siempre es el problema del día.
5) Tratas con versiones muy antiguas de Windows o hosts bloqueados
PowerShell 5.1 es común, PowerShell 7 no es universal y algunos servidores endurecidos tratan PowerShell como un arma cargada. CMD tiende a permitirse porque es “solo una shell”, lo cual es ingenuo pero convenientemente operativo.
Broma corta #1: CMD es como una transmisión manual: menos funciones, más control, y todos juran que pueden conducirla hasta que encuentran una cuesta.
Cuándo PowerShell gana (la mayoría de los días)
1) Cualquier cosa que implique consultas estructuradas
Si necesitas “todos los servicios que son Automáticos pero no están en Ejecución” o “todos los discos con menos del 10% libre”, PowerShell lo convierte en un único comando fiable. CMD lo convierte en parsear salida de texto y esperar que tu regex no devore un espacio.
2) Administración remota a escala
PowerShell Remoting (WinRM / WSMan) te da una forma estándar de ejecutar comandos remotamente, autenticar correctamente y devolver resultados estructurados. CMD puede hacer ejecución remota mediante herramientas de terceros, tareas programadas o hacks de la era WMI, pero PowerShell es la opción de primera clase.
3) Automatización más segura e idempotencia
Cuando escribes PowerShell con disciplina—parámetros explícitos, manejo de errores, -WhatIf en cmdlets compatibles y registro consistente—puedes construir operaciones repetibles. Los batch pueden ser repetibles también, pero su semántica de fallo es un pantano: los códigos de salida se pierden, las canalizaciones ocultan fallos y la expansión retardada es un círculo especial del infierno.
4) APIs modernas de gestión de Windows
Las superficies de gestión más nuevas aparecen primero en PowerShell: cmdlets CIM/WMI, cmdlets de almacenamiento, cmdlets de Hyper-V, Defender y herramientas de seguridad, integración con agentes en la nube. CMD no es donde aterriza la innovación.
5) Salida que puedes alimentar a otros sistemas
Cuando tu respuesta a incidentes espera JSON, o tu auditoría quiere CSV, PowerShell hace eso mundano. CMD puede hacerlo, pero se siente como tallar un violín a partir de un pallet.
Broma corta #2: La canalización de PowerShell es genial hasta que te das cuenta de que tu “one-liner” se volvió una novela con un giro de trama en Select-Object.
Datos históricos e contexto interesante (las partes que aún importan)
- CMD desciende de MS-DOS y del procesador de comandos de NT; es básicamente la interfaz administrativa más antigua y continuamente relevante de Windows.
- PowerShell empezó como “Monad”, diseñado para arreglar el problema de “parsear texto como API” empujando objetos por las canalizaciones.
- PowerShell está construido sobre .NET, por eso puedes alcanzar APIs profundas del sistema (y por eso el arranque y la carga de módulos pueden no ser triviales).
- Integradas de CMD vs programas externos: comandos como
dirysetson integrados de la shell, mientras queipconfiges un ejecutable—esto importa cuando PATH está roto. - Las utilidades de Windows a menudo mantuvieron su salida estable durante décadas; esa estabilidad explica por qué tantos scripts frágiles aún funcionan.
- La política de ejecución se convirtió en campo de batalla corporativo: las organizaciones la usaron como control, a veces sin entender qué evita realmente.
- PowerShell 5.1 es “Windows PowerShell” (incluido en muchas instalaciones), mientras que PowerShell 7+ es la línea multiplataforma “pwsh”: diferente runtime, diferente compatibilidad de módulos.
- WinRM estuvo deshabilitado por defecto en muchos clientes durante años, lo que ralentizó la adopción del remoting y mantuvo hábitos de “CMD remota”.
- Las rarezas de Batch son artefactos históricos: cosas como la semántica de
ERRORLEVELy la expansión retardada existen porque la compatibilidad fue tratado como voto sagrado.
Tareas prácticas: comandos, salidas y decisiones (12+ ejercicios)
Estos son deliberadamente tareas “reales de ops”: comprobaciones que ejecutas durante incidentes, migraciones y extrañas quejas de rendimiento. Cada tarea incluye un comando, salida típica, qué significa y qué decisión impulsa.
Task 1: Identify the OS and boot context quickly (CMD)
cr0x@server:~$ ver
Microsoft Windows [Version 10.0.17763.5458]
Qué significa: Confirma la familia de versión de Windows. Útil cuando el comportamiento difiere entre Server 2012/2016/2019/2022.
Decisión: Si estás en builds antiguos, espera PowerShell más viejo y cmdlets de almacenamiento antiguos; elige herramientas en consecuencia.
Task 2: Check hostname and domain membership (CMD)
cr0x@server:~$ echo %COMPUTERNAME% & echo %USERDOMAIN%
FS-23
CORP
Qué significa: Comprobación rápida de identidad; confirma que no estás en la máquina equivocada y si ejecutas en contexto de dominio.
Decisión: Si el dominio está mal o vacío, investiga problemas de confianza/autenticación antes de perseguir “latencia de red”.
Task 3: Confirm you’re elevated (CMD)
cr0x@server:~$ whoami /groups | findstr /i "S-1-5-32-544"
BUILTIN\Administrators Alias S-1-5-32-544 Mandatory group, Enabled by default, Enabled group
Qué significa: Estás en el grupo Administradores local; muchas operaciones de almacenamiento/red/servicio requieren esto.
Decisión: Si no estás elevado, vuelve a ejecutar como admin antes de culpar “Access is denied” a GPO o herramientas de seguridad.
Task 4: Check IP configuration and detect “wrong NIC” problems (CMD)
cr0x@server:~$ ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . : FS-23
Primary Dns Suffix . . . . . . . : corp.example
Ethernet adapter Ethernet0:
DHCP Enabled. . . . . . . . . . : No
IPv4 Address. . . . . . . . . . : 10.40.12.23(Preferred)
Subnet Mask . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . : 10.40.12.1
DNS Servers . . . . . . . . . . : 10.40.1.10
10.40.1.11
Qué significa: Confirma IP, gateway, DNS. “Preferred” sugiere que la pila está contenta.
Decisión: Si los servidores DNS son erróneos o faltan, arregla la resolución de nombres antes de profundizar en misterios de SMB o AD.
Task 5: Fast DNS sanity check (CMD)
cr0x@server:~$ nslookup fileshare01
Server: dns01.corp.example
Address: 10.40.1.10
Name: fileshare01.corp.example
Address: 10.40.12.55
Qué significa: El nombre se resuelve y sabes qué servidor DNS respondió.
Decisión: Si expira el tiempo de espera o resuelve a una IP inesperada, detente. Arregla DNS o entradas obsoletas; no “optimices SMB”.
Task 6: Quick route validation (CMD)
cr0x@server:~$ route print | findstr /i "0.0.0.0"
0.0.0.0 0.0.0.0 10.40.12.1 10.40.12.23 25
Qué significa: La ruta por defecto apunta donde crees. La métrica muestra la preferencia.
Decisión: Si la ruta por defecto está mal (común en servidores multi-homed), arregla el enrutamiento antes de culpar “timeouts aleatorios”.
Task 7: Measure basic reachability vs path issues (CMD)
cr0x@server:~$ ping -n 4 10.40.12.55
Pinging 10.40.12.55 with 32 bytes of data:
Reply from 10.40.12.55: bytes=32 time<1ms TTL=128
Reply from 10.40.12.55: bytes=32 time<1ms TTL=128
Reply from 10.40.12.55: bytes=32 time<1ms TTL=128
Reply from 10.40.12.55: bytes=32 time<1ms TTL=128
Ping statistics for 10.40.12.55:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Qué significa: ICMP funciona; la latencia parece local. No prueba que la aplicación funcione, pero reduce el radio del problema.
Decisión: Si hay pérdida de paquetes, trátalo como un problema de red hasta que se demuestre lo contrario; no optimices scripts de PowerShell.
Task 8: Validate SMB connectivity and session state (CMD)
cr0x@server:~$ net use
New connections will be remembered.
Status Local Remote Network
-------------------------------------------------------------------------------
OK Z: \\fileshare01\dept Microsoft Windows Network
The command completed successfully.
Qué significa: Tienes una unidad mapeada y está OK actualmente.
Decisión: Si los mapeos fallan, verifica credenciales y sincronización Kerberos antes de “reiniciar LanmanServer”.
Task 9: Check disk space quickly (CMD)
cr0x@server:~$ wmic logicaldisk get name,freespace,size
FreeSpace Name Size
21474836480 C: 127999999488
1099511627776 D: 2199023255552
Qué significa: El espacio está en bytes. C: tiene ~20 GB libres; D: tiene ~1 TB libre.
Decisión: Si el espacio libre es escaso en la unidad del sistema, espera fallos de servicios, fallos de parcheo y bloqueos de escritura de logs. Limpia primero.
Task 10: Check service state fast (CMD)
cr0x@server:~$ sc query LanmanServer
SERVICE_NAME: LanmanServer
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
Qué significa: El servicio servidor SMB está en ejecución y no reporta errores.
Decisión: Si está DETENIDO o inestable, tienes problemas de dependencias o agotamiento de recursos; ve a logs de eventos y latencia de almacenamiento.
Task 11: Query recent critical system events (CMD, classic and reliable)
cr0x@server:~$ wevtutil qe System /q:"*[System[(Level=1 or Level=2)]]" /c:5 /f:text
Event[0]:
Log Name: System
Source: disk
Event ID: 7
Level: Error
Description:
The device, \Device\Harddisk2\DR2, has a bad block.
Qué significa: La capa de disco está reportando bloques defectuosos. Eso no es “la red”. No es “PowerShell lento”. Es almacenamiento.
Decisión: Escala a hardware/almacenamiento inmediatamente; deja de hacer “ajustes de rendimiento”. Recopila diagnósticos SMART/vendedor y planifica reemplazo.
Task 12: Get process CPU hogs (PowerShell)
cr0x@server:~$ powershell -NoProfile -Command "Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name,Id,CPU,WorkingSet64"
Name Id CPU WorkingSet64
sqlservr 4216 9883 12728471552
MsMpEng 1712 622 398524416
svchost 1100 401 172425216
w3wp 5024 389 612978688
System 4 201 89579520
Qué significa: El tiempo de CPU es acumulativo desde el inicio del proceso. WorkingSet64 es memoria en bytes.
Decisión: Si Defender (MsMpEng) está caliente durante un incidente en un servidor de archivos, considera exclusiones de escaneo para rutas de datos de alto churn—con cautela y aprobación de seguridad.
Task 13: Identify top memory consumers (PowerShell)
cr0x@server:~$ powershell -NoProfile -Command "Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 5 Name,Id,@{n='WS_GB';e={[math]::Round($_.WorkingSet64/1GB,2)}}"
Name Id WS_GB
sqlservr 4216 11.85
w3wp 5024 0.57
MsMpEng 1712 0.37
explorer 3120 0.22
svchost 1100 0.16
Qué significa: Muestra working set en GB. Útil para comprobaciones rápidas de “¿la máquina está haciendo swapping hasta morir?”
Decisión: Si la presión de memoria es alta y se sospecha paginación, confirma con contadores de rendimiento antes de reiniciar servicios a ciegas.
Task 14: Check disk health and layout (PowerShell storage cmdlets)
cr0x@server:~$ powershell -NoProfile -Command "Get-PhysicalDisk | Select-Object FriendlyName,MediaType,HealthStatus,OperationalStatus,Size"
FriendlyName MediaType HealthStatus OperationalStatus Size
NVMe0 SSD Healthy OK 1024 GB
SAS01 HDD Warning OK 4000 GB
SAS02 HDD Healthy OK 4000 GB
Qué significa: La pila de almacenamiento ve un disco en Warning. Eso a menudo predice fallo, no es una falsa alarma.
Decisión: Si algún disco está en Warning/Unhealthy, deja de optimizar y empieza la gestión de fallos: verifica estado RAID, repuesto caliente, rebuild, backups.
Task 15: Measure SMB server performance counters quickly (PowerShell)
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\SMB Server Shares(*)\Avg. sec/Read' -SampleInterval 1 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue"
Path CookedValue
\\FS-23\SMB Server Shares(dept)\Avg. sec/Read 0.0021
\\FS-23\SMB Server Shares(dept)\Avg. sec/Read 0.0019
\\FS-23\SMB Server Shares(dept)\Avg. sec/Read 0.0450
Qué significa: La latencia de lectura es en general buena pero tiene picos a 45ms en una muestra. Huele a almacenamiento backend o drivers filtro.
Decisión: Si los picos de latencia coinciden con quejas de usuarios, pivota a cola/latencia de disco y drivers AV/filtro, no a “flags de tuning de SMB”.
Task 16: Verify time sync (Kerberos and “mysterious auth failures”) (CMD)
cr0x@server:~$ w32tm /query /status
Leap Indicator: 0(no warning)
Stratum: 4 (secondary reference - syncd by (S)NTP)
Precision: -23 (119.209ns per tick)
Last Successful Sync Time: 2/5/2026 1:52:10 AM
Source: dc01.corp.example
Poll Interval: 6 (64s)
Qué significa: La máquina se sincronizó recientemente y con una fuente sensata.
Decisión: Si el tiempo deriva o la fuente es incorrecta, arregla el tiempo antes de perseguir “credenciales erróneas” y “problemas de SPN”.
Task 17: Check WinRM readiness for PowerShell remoting (CMD)
cr0x@server:~$ winrm quickconfig
WinRM service is already running on this machine.
WinRM is already set up for remote management on this computer.
Qué significa: Los básicos de remoting están configurados.
Decisión: Si esto falla, planifica acceso alternativo (RDP/console) o arregla remoting antes de prometer “podemos ejecutarlo en 500 servidores”.
Task 18: Get installed PowerShell version and edition (PowerShell)
cr0x@server:~$ powershell -NoProfile -Command "$PSVersionTable | Select-Object PSVersion,PSEdition"
PSVersion PSEdition
--------- ---------
5.1.17763.5458 Desktop
Qué significa: Esto es Windows PowerShell 5.1 (edición Desktop), no PowerShell 7+ (Core).
Decisión: No asumas módulos multiplataforma o sintaxis moderna. Escribe scripts que funcionen en 5.1 o despliega pwsh intencionalmente.
Guion de diagnóstico rápido: encuentra el cuello de botella rápido
Ésta es la secuencia que uso cuando alguien dice “PowerShell está lento” o “CMD es más rápido” pero el sistema en realidad está asfixiado por otra cosa. El objetivo es identificar el recurso limitante en minutos, no ganar una discusión.
Primero: confirma el entorno y tu posición
- ¿Estás elevado? Si no, la mitad de tus comprobaciones mentirán por omisión (o simplemente fallarán).
- ¿Estás en la shell y versión correctas? PowerShell 5.1 vs 7 cambia la disponibilidad de módulos; los perfiles pueden añadir segundos de retraso.
- ¿El host está lo suficientemente sano para hacer diagnóstico? Si tiene poco disco C: o RAM, todas las herramientas se sienten lentas.
Segundo: determina si es CPU, memoria, disco o red
- CPU: Busca un consumidor alto que coincida con la ventana de la queja (escaneos AV, compresión, app desbocada).
- Memoria: Commit/paginación alta hace que las shells “cuelguen” mientras el sistema thrash.
- Disco: Picos de latencia y profundidad de cola causan que todo se estanque—especialmente la carga de módulos y lectura de perfiles de PowerShell.
- Red: Retrasos de DNS y detección automática de proxy son culpables clásicos de “PowerShell lento” porque muchos comandos disparan resolución de nombres o comprobaciones de certificados.
Tercero: aislar la sobrecarga de la shell de la sobrecarga del sistema
- Ejecuta PowerShell con
-NoProfilepara eliminar perfiles lentos y scripts. - Mide un cmdlet simple (como
Get-Date) frente a un cmdlet pesado de módulos (como almacenamiento/red). Si ambos son lentos, no es el módulo. - Llama al mismo EXE desde ambas shells (por ejemplo,
ipconfig). Si es lento en ambas, culpa al sistema o a las dependencias del EXE.
Cuarto: confirma la ruta de dependencias (¿en qué espera tu comando?)
- DNS: la resolución lenta puede bloquear llamadas remotas.
- Autenticación: deriva del tiempo o latencia AD puede estancar el remoting.
- Almacenamiento: lecturas lentas detienen todo, desde la importación de módulos hasta consultas de logs.
- Herramientas de seguridad: escaneo de scripts y hooks AMSI pueden añadir sobrecarga—a veces mucha.
Tres microhistorias del mundo corporativo (dolor, arrepentimiento y una victoria silenciosa)
Microhistoria #1: Un incidente causado por una suposición equivocada
El equipo tenía un runbook que empezaba con una verdad simple: “Usar PowerShell para todo”. Era un empuje de modernización y había dado frutos. Así que cuando un controlador de dominio no arrancó tras parchear, el ingeniero on-call siguió el runbook—abrió PowerShell en recuperación, intentó cargar las herramientas habituales y se estrelló. El entorno no tenía lo que el runbook asumía.
Gastaron tiempo intentando montar módulos y ejecutar cmdlets que no estaban presentes. Mientras tanto, la necesidad real era básica: inspeccionar la configuración de arranque, confirmar letras de volumen en WinRE (que tienden a cambiar) y revertir un driver malo. CMD podría haber hecho todo eso con integradas y utilidades clásicas.
Eventualmente alguien senior preguntó “en qué shell estás” y cambió a CMD. Usaron bcdedit y operaciones de archivos básicas para validar las entradas de arranque y detectar el desajuste entre el mapeo de volúmenes esperado y el real. Después fue mecánico: corregir la referencia de arranque, confirmar el hive del sistema correcto, reiniciar.
El postmortem no trató de que PowerShell fuera malo. Trató de asumir la presencia de tu entorno preferido en el momento exacto en que necesitas la cadena mínima de dependencias. La solución fue simple y aburrida: el runbook obtuvo una rama “Recovery mode” que por defecto usa CMD y lista los pocos comandos que realmente funcionan en ese contexto.
Microhistoria #2: Una optimización que salió mal
Un grupo de plataforma quería colecciones de logs más rápidas durante incidentes. Tenían un script de PowerShell que consultaba logs de eventos, filtraba por tiempo y exportaba resultados como JSON para una herramienta interna. Era correcto, pero no era lo suficientemente rápido cuando se ejecutaba en muchos hosts.
Así que “optimizaron” reemplazando consultas estructuradas por un enfoque que parecía más rápido: llamar a wevtutil desde PowerShell y parsear el texto. Rindió bien en algunos equipos. Lo desplegaron.
Dos meses después, durante una interrupción, el colector produjo resultados vacíos para un conjunto de servidores en otra configuración regional. La salida de texto tenía un formato ligeramente distinto. La regex no coincidió. El equipo de incidentes perdió tiempo porque el tablero dijo “sin errores”, mientras los servidores gritaban en el log System.
Revirtieron al enfoque basado en objetos y luego optimizaron correctamente: reducir el alcance de la consulta, usar filtrado del lado del servidor cuando fuera posible y agrupar llamadas remotas. La lección: los hacks de rendimiento que cambian estructura por velocidad de parsing suelen fallar, y lo hacen en el peor momento posible—cuando necesitas que los datos sean inequívocos.
Microhistoria #3: Una práctica aburrida pero correcta que salvó el día
Otra compañía, otra flota Windows con mucho almacenamiento. Sus servidores de archivos eran estables, pero el equipo tenía un hábito: cada servidor tenía un pequeño “kit de triage” documentado en un archivo de texto local y referenciado en el sistema de runbooks. Incluía comandos CMD y PowerShell, cada uno elegido por el entorno donde es más fiable.
Durante un incidente relacionado con un ransomware, los controles de seguridad se endurecieron rápido. La ejecución de scripts PowerShell quedó muy restringida y algunas herramientas remotas fueron bloqueadas por cambios de política. Los SRE on-call aún podían iniciar sesión, pero muchas vías de automatización se cortaron.
El kit de triage no se inmutó. Se basaba en comprobaciones locales directas: estado de servicio con sc, red con ipconfig y route, muestreo de logs de eventos con wevtutil y comprobaciones de salud de almacenamiento con PowerShell ejecutado en modo -NoProfile para minimizar la sobrecarga. Pudieron determinar qué hosts estaban afectados, cuáles sanos y dónde estaba el cuello de botella (latencia de disco y drivers filtro) sin pelear con la capa de política.
Sin heroicidades. Sin ingenios. Solo una secuencia de diagnóstico práctica y de dependencia mínima que funcionó bajo presión. Ese es el tipo de “aburrido” que quieres.
Errores comunes: síntoma → causa raíz → arreglo
1) “PowerShell tarda en abrir”
Síntoma: La consola se abre pero tarda varios segundos antes de aceptar entrada.
Causa raíz: Scripts de perfil pesados, carga automática de módulos o escaneo por herramientas de seguridad en rutas de perfil/módulos.
Arreglo: Usa powershell -NoProfile para trabajo de incidentes. Audita el contenido de $PROFILE y elimina importaciones costosas. Si las herramientas de seguridad enganchan escaneo de scripts, coordina exclusiones para scripts administrativos conocidos y firmados—no exclusiones amplias.
2) “Mi script funciona en PowerShell pero falla en CMD”
Síntoma: Comandos con comillas y paréntesis se comportan distinto; las variables no se expanden.
Causa raíz: Reglas diferentes de comillas y expansión de variables. CMD usa %VAR% y tiene trampas de expansión retardada; PowerShell usa $var y trata las cadenas de forma distinta.
Arreglo: No pegues sintaxis de PowerShell en CMD ni viceversa. Si debes llamar una shell desde la otra, sé explícito y mantén los argumentos simples.
3) “La tubería de CMD no falló, pero la tarea no funcionó”
Síntoma: El archivo por lotes continúa incluso después de que un comando falla; los logs muestran texto que parece éxito.
Causa raíz: Códigos de salida perdidos en pipelines o sobrescritos por comandos posteriores; mal uso de ERRORLEVEL.
Arreglo: Comprueba if errorlevel 1 inmediatamente tras el comando. Evita pipear cuando necesites estado de salida exacto. Considera envolver pasos críticos en PowerShell donde el manejo de errores es más controlable.
4) “El remoting de PowerShell falla, pero RDP funciona”
Síntoma: Enter-PSSession o Invoke-Command falla con errores de acceso/transporte.
Causa raíz: WinRM no está configurado, reglas de firewall faltan, problemas de SPN/Kerberos o delegación restringida.
Arreglo: Valida la configuración de WinRM localmente con winrm quickconfig. Confirma DNS y sincronización de tiempo. Revisa la política de firewall. Si la política corporativa bloquea WinRM, usa métodos remotos alternativos aprobados y documéntalos.
5) “El parseo de texto se rompió después de parchear”
Síntoma: Un script por lotes que raspa salida de net/sc/wevtutil de repente devuelve datos vacíos.
Causa raíz: Formato de salida cambiado sutilmente; configuración regional diferente; columnas refluídas.
Arreglo: Deja de parsear salidas orientadas a humanos cuando sea posible. En PowerShell, usa cmdlets que devuelvan objetos. Si debes parsear, restringe la localización y usa formatos estables (CSV/JSON) cuando estén disponibles.
6) “PowerShell dice acceso denegado aunque soy admin”
Síntoma: El usuario admin puede ejecutar herramientas CMD pero los cmdlets de PowerShell fallan.
Causa raíz: Problemas de token UAC, Modo de Lenguaje Restringido, políticas AppLocker/WDAC o privilegios faltantes en el contexto del proceso.
Arreglo: Verifica la elevación, comprueba el modo de lenguaje y prueba con -NoProfile. Si hay políticas de control de aplicaciones, trabaja con seguridad para aprobar scripts firmados y binarios administrativos conocidos.
Listas de verificación / plan paso a paso
Lista: elegir CMD vs PowerShell en el momento
- ¿Estás en WinRE/Modo Seguro/entorno mínimo? Por defecto usa CMD.
- ¿Necesitas filtrado/reportes/exportación estructurada? Por defecto usa PowerShell.
- ¿El sistema está inestable (errores de disco, presión de memoria)? Prefiere la vía de menor sobrecarga: CMD + EXEs dirigidos, y PowerShell solo con
-NoProfile. - ¿Trabajas de forma remota en muchos hosts? Prefiere PowerShell remoting, pero verifica WinRM y políticas primero.
- ¿La tarea es inherentemente una utilidad clásica? Usa la utilidad directamente; no la envuelvas a menos que necesites estructura y puedas mantener el parsing fiable.
Paso a paso: construir un runbook “dos shells” que sobreviva a incidentes
- Escribe cada comprobación crítica dos veces: un método compatible con CMD y otro con PowerShell. Elige el autoritativo y etiqueta el fallback.
- Estandariza la invocación de PowerShell: usa
-NoProfileen runbooks a menos que necesites explícitamente una función de perfil. - Registra salidas crudas para forenseo: almacena el comando exacto y la salida en el ticket/notas del incidente.
- Define un conjunto mínimo de diagnósticos: identidad, sincronización de tiempo, DNS, ruta, espacio en disco, errores en el log de eventos, salud de servicios.
- Practica en modos degradados: prueba el runbook en una VM en Modo Seguro o condiciones simuladas de “disco lleno”. Aquí es donde las suposiciones mueren.
- Ten un disparador de escalado: “Si el disco muestra Warning/Unhealthy o el log System tiene errores de disco, detente y contacta almacenamiento/hardware”.
Paso a paso: reescribir un job batch frágil a PowerShell sin romper producción
- Congela el comportamiento: captura entradas/salidas actuales y códigos de salida. Si no sabes cómo luce el “éxito”, lanzarás una regresión.
- Reemplaza el parsing primero: cambia de scraping de texto a consultas de objetos cuando sea posible.
- Haz los errores ruidosos: establece manejo estricto de errores y devuelve códigos de salida significativos a los llamadores.
- Despliega en paralelo: ejecuta la versión PowerShell en modo “observación” mientras el batch sigue haciendo el trabajo real.
- Corte gradual: primero un pequeño conjunto de servidores; compara resultados.
- Documenta el rollback: en ops, el rollback es una característica, no una admisión de derrota.
Preguntas frecuentes
1) ¿CMD está obsoleto?
No. Es viejo, no muerto. CMD sigue siendo la línea base más fiable cuando Windows está en un estado reducido, y muchas utilidades nucleares siguen siendo herramientas “de la era CMD”.
2) ¿Debería dejar de escribir archivos por lotes?
Para la automatización nueva: sí, en su mayoría. Usa PowerShell para todo lo que requiera corrección, estructura y mantenibilidad. Mantén batch para integración heredada y entornos restringidos donde rehacer añade riesgo.
3) ¿Por qué PowerShell a veces se siente más lento aun cuando el comando es simple?
La sobrecarga de arranque (perfiles, descubrimiento de módulos), el escaneo de seguridad y la inicialización de .NET pueden dominar operaciones “simples”. Usa -NoProfile para trabajo de incidentes y evita personalizaciones pesadas de perfil en servidores.
4) ¿PowerShell puede ejecutar comandos de CMD?
Sí—PowerShell puede ejecutar cualquier ejecutable. Pero ten cuidado con las comillas y con comandos que son integrados de la shell (como dir), que PowerShell puede aliasar o interpretar de forma distinta.
5) ¿Cuál es la mayor diferencia práctica en scripting?
Manejo de errores y tipos de datos. PowerShell te permite trabajar con objetos estructurados y manejar excepciones. Batch a menudo te fuerza a inferir estado desde texto y códigos de salida, lo cual es más frágil.
6) ¿El remoting de PowerShell siempre es la mejor opción remota?
Es la opción nativa de Windows más limpia cuando WinRM está disponible y la política lo permite. En entornos muy bloqueados puedes necesitar métodos alternativos aprobados. El error es asumir que remoting está habilitado en todas partes.
7) ¿Necesito PowerShell 7?
No necesariamente. Muchos módulos de administración de Windows apuntan a 5.1. PowerShell 7 es excelente para scripting multiplataforma y mejoras de rendimiento, pero la compatibilidad de módulos y la realidad del despliegue empresarial importan.
8) ¿Cómo evito la trampa de “script PowerShell bloqueado por política” durante incidentes?
Tén un plan que no dependa de scripts no firmados ejecutándose ad-hoc. Usa scripts firmados para automatización estandarizada, mantiene un fallback basado en CMD para triage básico y documenta cómo ejecutar PowerShell con dependencias mínimas.
9) ¿Parsing de texto siempre es malo?
No, solo arriesgado. En emergencias, parsear texto puede ser pragmático. Para automatización de larga vida, prefiere salidas estructuradas y consultas basadas en objetos, porque “funciona hoy” no es una estrategia de confiabilidad.
Siguientes pasos que realmente puedes aplicar
Deja de preguntar “¿Qué shell es mejor?”. Pregunta “¿Qué shell falla menos para este escenario?”. PowerShell debería ser tu predeterminado para automatización, informes y escala. CMD debería ser tu reserva para recuperación, entornos mínimos y esas utilidades clásicas que aún dicen la verdad cuando todo lo demás está en llamas.
Haz esto a continuación:
- Crea un kit de triage de dos shells para tus roles de servidor principales (archivo, web, BD, controladores de dominio). Manténlo corto y ejecutable.
- Estandariza el uso de PowerShell en incidentes:
-NoProfile, parámetros explícitos y salidas limpias. - Elimina el parsing frágil con el tiempo: reemplaza scraping de texto por consultas de objetos, pero no “optimices” haciendo tus datos menos fiables.
- Practica en modos degradados: WinRE, disco lleno, política restringida. Ahí es donde CMD aún gana su lugar.
Si haces esas cuatro cosas, pasarás menos tiempo peleando con tus herramientas y más tiempo arreglando el sistema. Que es todo el trabajo.