Esta es probablemente una de las preguntas más frecuentes sobre PowerShell Universal. ¿Por qué mi script no funciona igual en PowerShell Universal que en un símbolo del sistema de PowerShell? Esta entrada ofrece contexto y pasos que puede seguir para identificar problemas al ejecutar sus scripts en la plataforma.
Versiones de PowerShell
Debe conocer las versiones que intervienen al ejecutar scripts en PowerShell Universal. Es fácil seleccionar distintas versiones de PowerShell, así que asegúrese de ejecutar el script en la versión prevista.
Las versiones de PowerShell aparecen en la página Platform > Environments. Cuando actualiza PowerShell 7, PowerShell Universal usa automáticamente la que está en la ruta predeterminada. También es posible instalar versiones de PowerShell 7 en paralelo y configurar PowerShell Universal para usar varias.
Un problema habitual son los módulos que no funcionan de forma nativa en PowerShell 7. En ese caso entra Windows PowerShell Compatibility. Parecerá que funciona como se espera, pero en segundo plano se inician nuevos procesos de Windows PowerShell. Cada runspace que usa el módulo de Windows PowerShell en el entorno de PowerShell 7 inicia un proceso nuevo. Esto puede reducir el rendimiento de forma considerable.
Entorno integrado
El entorno integrado es una versión del SDK de PowerShell 7 incluida en PowerShell Universal. No cambia al actualizar PowerShell en el equipo host. Solo cambia cuando una nueva versión de PowerShell Universal actualiza la versión del SDK de PowerShell.
El entorno integrado es rápido porque no necesita iniciar procesos externos ni comunicar a través de un canal RPC. El inconveniente es que es un único punto de fallo para todos los scripts, las API y los dashboards, ya que comparten el mismo espacio de proceso. También puede encontrar conflictos de ensamblados al cargar muchos módulos que usan ensamblados .NET comunes.
Esto ocurre con frecuencia con la biblioteca Newtonsoft.Json. Los scripts que usan módulos integrados o ningún módulo son excelentes candidatos para el entorno integrado.
Permisos y privilegios
Ejecutar un script como usuario local en un equipo puede ser muy distinto de ejecutarlo en PowerShell Universal cuando está hospedado como servicio o en IIS. Debe saber dónde están instalados sus módulos, porque PowerShell Universal puede no descubrirlos en el mismo sitio.
Además, si hospeda como servicio y el módulo necesita interactuar con el escritorio (como Selenium), deberá configurar el servicio con especial cuidado.
IIS restringe aún más al usuario del grupo de aplicaciones al limitar los privilegios de la cuenta al ejecutarse. Eso significa que acceder a determinados directorios o elevarse a otra cuenta puede causar problemas aunque el usuario sea administrador. Un ejemplo: New-WebServiceProxy no funciona en IIS porque el cmdlet intenta escribir archivos C# y compilarlos desde el disco, y el grupo de aplicaciones no tiene ese privilegio.
Puede usar la función Terminal de PowerShell Universal para investigar el entorno configurado actualmente y ver las diferencias.
Hosts personalizados
PowerShell Universal tiene dos hosts personalizados. El primero se usa al ejecutar scripts como trabajos. Este host incluye funciones como esperar comentarios y escribir en distintos flujos. El segundo se usa para el resto de operaciones en PowerShell Universal. No implementa funciones de host personalizadas salvo el registro.
Si olvida parámetros o pide comentarios al usuario, con algo como Read-Host, en un host que no lo admite, recibirá errores. La práctica recomendada es evitar este tipo de interacción en PowerShell Universal.
Estado de runspace de corta duración
PowerShell Universal usa grupos de runspaces para la mayor parte de la funcionalidad del sistema. Crea runspaces cuando hacen falta y los libera cuando no. Tras cada ejecución de una función, como una API o un endpoint de dashboard, el estado del runspace se restablece.
Esto puede afectar a scripts que usan funciones de PowerShell como sesiones o remoting. No podrá usar sesiones entre llamadas a endpoints a menos que active la función persistent runspace.
Proceso de larga duración
PowerShell Universal está diseñado para ejecutarse durante un periodo prolongado. Limpiamos recursos periódicamente y reciclamos runspaces tras un número de usos o un tiempo determinado. Algunos módulos de PowerShell no están bien diseñados para este tipo de entorno de ejecución. Esperan ejecutarse en un proceso de PowerShell que invoca un script y luego termina.
Para mitigarlo, puede ejecutar los scripts como trabajos en procesos externos, de modo que todos los recursos se limpien cuando el script haya terminado. Ciertos módulos como PowerCLI y dbatools tienen clases .NET estáticas que pueden mantener estado y consumir memoria incluso cuando se liberan los runspaces y se ejecuta el recolector de basura de .NET.
IIS puede reciclar el proceso de PowerShell Universal a intervalos, cuando se alcanzan ciertos límites de recursos o cuando el servidor no se está usando.
Gestión de secretos
La implementación de gestión de secretos de PowerShell Universal se basa en los módulos Microsoft SecretManagement. La instalación predeterminada incluye el módulo principal junto con varios módulos de almacén.
Todos los almacenes incluidos de forma predeterminada implementan mecanismos de almacenamiento específicos del usuario. Si cambia la cuenta de usuario del servicio de PowerShell Universal, ya no podrá acceder a los secretos. Eso también significa que, si crea secretos en su entorno local con su propio usuario, es probable que PowerShell Universal no pueda acceder a esos secretos.
Conclusión
Esta entrada debería haberle dado contexto para identificar problemas al ejecutar scripts en PowerShell Universal.
¿Listo para crear? Descargue PowerShell Universal.

Adam Driscoll