uso de PSScriptAnalyzer para comprobar la compatibilidad de la versión de PowerShell
PSScriptAnalyzer Versión 1.18 fue lanzado recientemente, y viene con nuevas y potentes reglas que pueden comprobar scripts de PowerShell en busca de incompatibilidades con otras versiones y entornos de PowerShell.
en esta entrada de blog, la primera de una serie, veremos cómo usar estas nuevas reglas para comprobar si un script tiene problemas en PowerShell 3, 5.1 y 6.
espera, ¿Qué es PSScriptAnalyzer?,
PSScriptAnalzyer es un módulo que proporciona análisis estático (o linting) y algunos análisis dinámicos (basados en el estado del entorno) para PowerShell. Es capaz de encontrar problemas y corregir malos hábitos en los scripts de PowerShell a medida que los crea, de forma similar a la forma en que el compilador de C# le dará advertencias y encontrará errores en el código de C# antes de que se ejecute.,
Si utiliza la extensión VSCode PowerShell, es posible que haya visto los «Green squigglies» y los informes de problemas que genera PSScriptAnalyzer para los scripts que ha escrito:
puede instalar PSScriptAnalyzer para usar en sus propios scripts con:
Install-Module PSScriptAnalyzer -Scope CurrentUser
Psscriptanalyzer funciona ejecutando una serie de reglas en sus scripts, cada una de las cuales Evalúa de forma independiente algún problema., Por ejemplo, AvoidUsingCmdletAliases
comprueba que los alias no se utilicen en los scripts, y MisleadingBackticks
comprueba que los backsticks al final de las líneas no vayan seguidos de espacios en blanco.
para obtener más información, consulte la serie de blogs PSScriptAnalyzer deep dive.
introducción de las reglas de comprobación de compatibilidad
la nueva funcionalidad de comprobación de compatibilidad se proporciona mediante tres reglas nuevas:
- PSUseCompatibleSyntax, que comprueba si una sintaxis utilizada en un script funcionará en otras versiones de PowerShell.,
- PSUseCompatibleCommands, que comprueba si los comandos utilizados en un script están disponibles en otros entornos de PowerShell.
- PSUseCompatibleTypes, que comprueba si los tipos. NET y los métodos/propiedades estáticos están disponibles en otros entornos de PowerShell.
la regla de comprobación de sintaxis simplemente requiere una lista de las versiones de PowerShell a las que desea dirigirse y le indicará si una sintaxis utilizada en el script no funcionará en ninguna de esas versiones.,
Las reglas de comprobación de comandos y tipos son más sofisticadas y se basan en perfiles (catálogos de comandos y tipos disponibles) de plataformas PowerShell de uso común. Requieren configuración para usar estos perfiles, que veremos a continuación.
para esta publicación, veremos la configuración y el uso de PSUseCompatibleSyntax y PSUseCompatibleCommands para comprobar que un script funciona con diferentes versiones de PowerShell. Veremos PSUseCompatibleTypes en un post posterior, aunque está configurado de manera muy similar a PSUseCompatibleCommands.,
ejemplo de trabajo: un pequeño script de PowerShell
Imagine que tenemos un pequeño (y artificial) script de archivo guardado en.\archiveScript.ps1
:
Este script fue escrito en PowerShell 6.2, y hemos probado que funciona allí. Pero también queremos ejecutarlo en otras máquinas, algunas de las cuales ejecutan PowerShell 5.1 y otras ejecutan PowerShell 3.0.
idealmente lo probaremos en esas otras plataformas, pero sería bueno si pudiéramos intentar solucionar tantos errores como sea posible con anticipación.,
comprobación de sintaxis con PSUseCompatibleSyntax
La primera y más fácil regla de aplicar es PSUseCompatibleSyntax. Vamos a crear algunos ajustes para PSScriptAnalyzer para habilitar la regla, y luego ejecutar análisis en nuestro script para recuperar cualquier diagnóstico sobre la compatibilidad.
Ejecutar PSScriptAnalyzer es sencillo., Viene como un módulo de PowerShell, por lo que una vez que está instalado en la ruta del módulo, solo invoca en su archivo con Invoke-ScriptAnalyzer
, así:
Invoke-ScriptAnalyzer -Path ".\archiveScript.ps1`
una invocación muy simple como esta ejecutará PSScriptAnalyzer utilizando sus reglas y configuraciones predeterminadas en el script al que lo apunte.
sin embargo, debido a que requieren una configuración más específica, las reglas de compatibilidad no están habilitadas de forma predeterminada. En su lugar, necesitamos proporcionar algunas configuraciones para ejecutar la regla de comprobación de sintaxis., En particular, PSUseCompatibleSyntax requiere una lista de las versiones de PowerShell a las que se dirige el script.
ejecutar esto nos presentará la siguiente salida:
esto nos indica que la sintaxis ]::new()
que usamos no funcionará en PowerShell 3. Mejor que eso, en este caso la regla ha propuesto una corrección:
$diagnostics = Invoke-ScriptAnalyzer -Path .\archiveScript.ps1 -Settings $settings$diagnostics.SuggestedCorrections
la corrección sugerida es usar New-Object
en su lugar., La forma en que se sugiere esto puede parecer un poco inútil aquí con toda la información de posición, pero veremos más adelante por qué esto es útil.
este ejemplo de diccionario es un poco artificial, por supuesto (ya que una tabla hash sería más natural), pero tener una llave inglesa lanzada en las obras en PowerShell 3 o 4 debido a un ::new()
no es raro. La regla PSUseCompatibleSyntax también le avisará sobre clases, flujos de trabajo y sentencias using
dependiendo de las versiones de PowerShell para las que esté creando.,
todavía no vamos a hacer el cambio sugerido, ya que hay más para mostrarte primero.
Comprobar el uso de comandos con PSUseCompatibleCommands
ahora queremos comprobar los comandos. Debido a que la compatibilidad de comandos es un poco más complicada que la sintaxis (ya que la disponibilidad de comandos depende de más de qué versión de PowerShell se está ejecutando), tenemos que dirigir los perfiles en su lugar.
los perfiles son catálogos de información tomada de máquinas de stock que ejecutan entornos comunes de PowerShell., Los enviados en PSScriptAnalyzer no siempre pueden coincidir perfectamente con su entorno de trabajo, pero se acercan bastante (también hay una forma de generar su propio perfil, detallado en una publicación de blog posterior). En nuestro caso, estamos intentando dirigirnos a PowerShell 3.0, PowerShell 5.1 y PowerShell 6.2 en Windows. Tenemos los dos primeros perfiles, pero en el último caso tendremos que apuntar a 6.1 en su lugar. Estos destinos están muy cerca, por lo que las advertencias seguirán siendo pertinentes al uso de PowerShell 6.2. Más tarde, cuando un perfil 6.2 esté disponible, podremos cambiar a eso.,
necesitamos buscar en la documentación PSUseCompatibleCommands una lista de perfiles disponibles por defecto. Para nuestros objetivos deseados elegimos:
los nombres largos a la derecha son identificadores de perfil canónicos, que usamos en la configuración:
Puede haber un retraso la primera vez que ejecuta esto porque las reglas tienen que cargar los catálogos en una caché. Cada catálogo de una plataforma de PowerShell contiene detalles de todos los módulos y .,Ensamblados de red disponibles para PowerShell en esa plataforma, que pueden ser hasta 1700 comandos con 15 000 parámetros y 100 ensamblados con 10 000 tipos. Pero una vez que se cargue, el análisis de compatibilidad adicional será rápido. Tenemos una salida como esta:
RuleName Severity ScriptName Line Message-------- -------- ---------- ---- -------PSUseCompatibleCommands Warning archiveScr 2 The parameter "FullyQualifiedName" is not available for ipt.ps1 command "Import-Module" by default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 12 The command "Get-FileHash" is not available by default in ipt.ps1 PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 18 The parameter "LeafBase" is not available for command ipt.ps1 "Split-Path" by default in PowerShell version "5.1.17763.316" on platform "Microsoft Windows Server 2019 Datacenter"PSUseCompatibleCommands Warning archiveScr 18 The parameter "LeafBase" is not available for command ipt.ps1 "Split-Path" by default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 19 The command "Compress-Archive" is not available by ipt.ps1 default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 23 The parameter "NoNewline" is not available for command ipt.ps1 "Out-File" by default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"
Este es el que nos dice que:
-
Import-Module
no admite-FullyQualifiedName
en PowerShell 3.0; -
Get-FileHash
no existe en PowerShell 3.0; -
Split-Path
no tiene-LeafBase
en PowerShell 5.1 o PowerShell 3.,0; -
Compress-Archive
no está disponible en PowerShell 3.0, y; -
Out-File
no admite-NoNewline
en PowerShell 3.0
Una cosa que usted notará es que el Get-FoldersToArchive
función no es ser advertido acerca de. Esto se debe a que las reglas de compatibilidad están diseñadas para ignorar los comandos proporcionados por el usuario; un comando solo se marcará como incompatible si está presente en algún perfil y no en uno de sus destinos.,
de nuevo, podemos cambiar el script para corregir estas advertencias, pero antes de hacerlo, Quiero mostrarte cómo hacer que esta sea una experiencia más continua; a medida que cambias tu script, quieres saber si los cambios que haces rompen la compatibilidad, y eso es fácil de hacer con los pasos a continuación.
usando un archivo de configuración para invocaciones repetidas
Lo primero que queremos es hacer que la invocación de PSScriptAnalyzer sea más automatizada y reproducible. Un buen paso hacia esto es tomar la configuración hashtable que hicimos y convertirlo en un archivo de datos declarativo, separando el «qué» Del «cómo».,
PSScriptAnalyzer aceptará una ruta a un PSD1 en el parámetro-Settings
, por lo que todo lo que necesitamos hacer es convertir nuestro hashtable en un archivo PSD1, que haremos./PSScriptAnalyzerSettings.psd1
. Observe que podemos combinar la configuración para PSUseCompatibleSyntax y PSUseCompatibleCommands:
Ahora podemos ejecutar PSScriptAnalyzer nuevamente en el script usando el archivo de configuración:
Invoke-ScriptAnalyzer -Path ./archiveScript.ps1 -Settings ./PSScriptAnalyzerSettings.psd1
esto da la salida:
RuleName Severity ScriptName Line Message-------- -------- ---------- ---- -------PSUseCompatibleCommands Warning archiveScr 1 The parameter "FullyQualifiedName" is not available for ipt.ps1 command "Import-Module" by default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 9 The command "Get-FileHash" is not available by default in ipt.ps1 PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 12 The parameter "LeafBase" is not available for command ipt.ps1 "Split-Path" by default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 12 The parameter "LeafBase" is not available for command ipt.ps1 "Split-Path" by default in PowerShell version "5.1.17763.316" on platform "Microsoft Windows Server 2019 Datacenter"PSUseCompatibleCommands Warning archiveScr 13 The command "Compress-Archive" is not available by ipt.ps1 default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleCommands Warning archiveScr 16 The parameter "NoNewline" is not available for command ipt.ps1 "Out-File" by default in PowerShell version "3.0" on platform "Microsoft Windows Server 2012 Datacenter"PSUseCompatibleSyntax Warning archiveScr 6 The constructor syntax ipt.ps1 "]::new()" is not available by default in PowerShell versions 3,4
ahora ya no dependemos de ninguna variable, y tenemos una especificación separada del análisis que desea., Con esto, podría ponerlo en entornos de integración continua, por ejemplo, para comprobar que los cambios en los scripts no rompen la compatibilidad.
Pero lo que realmente queremos es saber que los scripts de PowerShell estancia compatible como editarlos. Eso es a lo que se está construyendo el archivo de configuración, y también donde es más fácil hacer los cambios que necesita para que su script sea compatible. Para ello, queremos integrarnos con la extensión VSCode PowerShell.,
integración con VSCode para comprobar la compatibilidad sobre la marcha
como se explicó al inicio de esta publicación, la extensión VSCode PowerShell tiene soporte incorporado para PSScriptAnalyzer. De hecho, a partir de la versión 1.12.0, la extensión PowerShell viene con PSScriptAnalyzer 1.18, lo que significa que no necesita hacer nada más que crear un archivo de configuración para realizar el análisis de compatibilidad.
ya tenemos nuestro archivo de configuración listo para ir desde el último paso, por lo que todo lo que tenemos que hacer es apuntar la extensión de PowerShell al archivo en la configuración de VSCode.,
Puede abrir la configuración con Ctrl+, (use Cmd en lugar de Ctrl en macOS). En la vista Configuración, queremos PowerShell > Script Analysis: Settings Path
. En la vista settings.json
esto es "powershell.scriptAnalysis.settingsPath"
., Al ingresar una ruta relativa aquí encontrará un archivo de configuración en nuestro espacio de trabajo, por lo que simplemente colocamos ./PSScriptAnalyzerSettings.psd1
:
en la vista settings.json
esto se verá como:
"powershell.scriptAnalysis.settingsPath": "./PSScriptAnalyzerSettings.psd1"
ahora, al abrir el script en VSCode, vemos «Green squigglies» para advertencias de compatibilidad:
en el panel de problemas, obtendrá una descripción completa de todas las incompatibilidades:
arreglemos primero el problema de sintaxis., Si lo recuerda, PSScriptAnalyzer proporciona una corrección sugerida a este problema. VSCode se integra con las correcciones sugeridas de PSScriptAnalyzer y puede aplicarlas si hace clic en la bombilla o con Ctrl+Espacio cuando la región está bajo el cursor:
aplicando este cambio, el script es ahora:
Las otras incompatibilidades no tienen correcciones; por ahora PSUseCompatibleCommands sabe qué comandos están disponibles en cada plataforma, pero no qué sustituir cuando un comando no está disponible., Así que solo necesitamos aplicar algunos conocimientos de PowerShell:
terminamos con algo como esto (la implementación específica no es importante, pero tenemos algo que funcionará en todas las versiones):
debería notar que a medida que escribe, VSCode muestra un nuevo análisis de lo que está escribiendo y los garabatos verdes desaparecen. Cuando hayamos terminado, obtendremos una lista limpia de la compatibilidad del script:
esto significa que ahora podrá usar este script en todas las versiones de PowerShell a las que necesite dirigirse., Mejor, ahora tiene una configuración en su espacio de trabajo para que a medida que escribe más scripts, se verifique continuamente la compatibilidad. Y si sus objetivos de compatibilidad cambian, todo lo que necesita hacer es cambiar su archivo de configuración en un solo lugar para apuntar a sus objetivos deseados, en cuyo momento obtendrá análisis para sus plataformas de destino actualizadas.
resumen
esperamos que en esta entrada de blog tengas alguna idea de las nuevas reglas de compatibilidad que vienen con PSScriptAnalyzer 1.18.,
hemos cubierto cómo configurar y usar la regla de comprobación de compatibilidad de sintaxis, PSUseCompatibleSyntax, y la regla de comprobación de comandos, PSUseCompatibleCommands, ambas usando una configuración hashtable y un archivo settings PSD1.
también hemos analizado el uso de las reglas de compatibilidad con la extensión de PowerShell para VSCode, que vienen por defecto de la versión 1.12.0.
Si tiene la última versión de la extensión de PowerShell para VSCode (1.12.1), podrá configurar su archivo de configuración y obtener la comprobación de compatibilidad al instante.,
en la siguiente entrada del blog, veremos cómo usar estas reglas y PSUseCompatibleTypes (que comprueba si los tipos.NET y los métodos estáticos están disponibles en las plataformas de destino) se pueden usar para ayudarlo a escribir scripts que funcionen multiplataforma en Windows y Linux utilizando Windows PowerShell y PowerShell Core.
Rob Holt
Ingeniero de Software
PowerShell Equipo