Creación de módulos
Introducción
La palabra "módulo" generalmente evoca la idea de "modular". Se concibe como un elemento básico central, alrededor del cual se agrupan otros elementos más pequeños que completan su funcionalidad. Estos elementos pueden eliminarse, mejorarse, añadirse o incluso transferirse.

Ilustración de la modularidad en PowerShell
Lo mismo ocurre con los módulos PowerShell, aunque son algo más que simples complementos. De hecho, todos los comandos de PowerShell, especialmente los comandos básicos, están contenidos en módulos. Los módulos se introdujeron con PowerShell 2.0. Sustituyeron a los snapins, que aparecieron en la primera versión de PowerShell. Los snapins se siguen utilizando, pero Microsoft recomienda el uso de módulos, que son mucho más sencillos de configurar.
Los módulos permiten organizar adecuadamente el código. Sobre todo, facilitan el intercambio de código con colegas e incluso con toda la comunidad.
Cuando se escribió este libro, Microsoft tenía una lista de 11.554 módulos publicados en su plataforma de descargas PowerShell Gallery (véase el capítulo Gestión de módulos y paquetes). Esto da una idea de su verdadera relevancia y del impacto que pueden tener.
¿Qué tipos de archivos son? ¿Y qué pueden contener?
-
PSM1: archivo de script....
Módulo dinámico
La segunda opción para crear un módulo es el comando New-Module. Esto crea un módulo dinámico. Se carga en memoria y existe mientras dura la sesión de PowerShell. Esto significa que no se escribe en el disco y, por lo tanto, es invisible para el comando Get-Module (más adelante veremos cómo hacerlo visible). Sin embargo, las funciones creadas permanecen visibles a través del comando Get-Command.
Argumentos para el comando New-Module:
Parámetro |
Descripción |
ArgumentList |
Especifica un arreglo de valores para pasar al parámetro -ScriptBlock. |
AsCustomObject |
Devuelve el módulo como un CustomObject cuando se crea. A continuación, se puede asignar a una variable. Las funciones o cmdlets exportados se presentan como métodos de ese objeto. |
Cmdlet |
Filtra los cmdlets exportados desde el módulo. Para ello, es necesario especificar una lista con el nombre de los cmdlets a exportar. Por defecto, se exportan todos los cmdlets. Se admiten wildcards. |
Function |
Filtra las funciones exportadas desde -ScriptBlock. Misma sintaxis que el parámetro -Cmdlet. |
Name |
Especifica un nombre de módulo. Como es obligatorio, si el valor es nulo o está vacío, PowerShell genera un nombre de configuración aleatorio. Su nombre empieza por "_DynamicModule". Irá seguido de un GUID. |
ReturnResult |
Devuelve la salida del bloque de script, así como la creación del módulo. |
ScriptBlock |
Indica el contenido del módulo dinámico. Este bloque está delimitado por llaves. Las funciones deben ir separadas por un salto de línea o un punto y coma. Se podría decir que equivale al archivo PSM1 de un módulo script. |
Ahora se crearán...
Módulo binario
Los módulos binarios son una categoría particular dentro de los módulos de PowerShell. Contienen código compilado en un lenguaje .NET. Pueden citarse ejemplos en C#, en VB.NET e incluso en ASP.NET. Aunque el diseño de un módulo binario es similar al de un snapin, existen diferencias importantes entre ambos. La instalación de un snapin requiere derechos de administrador, lo que no ocurre con un módulo binario. Basta con copiar los archivos, como sucede con los módulos de script (salvo que se copien en una carpeta que requiera privilegios elevados, como Program Files).
Diseñar cmdlets en un lenguaje .NET resulta especialmente útil. Proporciona un tiempo de ejecución más rápido que las funciones PowerShell. Sin embargo, descubrir estas funciones está fuera del alcance de este libro. Está dirigido a desarrolladores. No obstante, en términos generales, se recomienda encarecidamente interesarse por el framework .NET, especialmente si se busca constantemente el rendimiento en los scripts y funciones de PowerShell. .NET ofrece una gran variedad de clases que permiten ahorrar una cantidad considerable de tiempo.
Módulo script
Los módulos script son los más conocidos porque son rápidos y fáciles de crear. También son sencillos de desplegar y de utilizar.
Crear un módulo es relativamente sencillo. Se puede almacenar en diferentes lugares. Para ello, conviene comprobar el contenido de la variable de entorno $Env:PSModulePath. Si el módulo creado no está contenido en uno de los directorios de esta variable, entonces no será descubierto automáticamente por PowerShell. También es posible modificar esta variable para añadir sus propias rutas de acceso.
Nota: si modifica esta variable, asegúrese de conservar los valores predeterminados ya existentes.
Si se decide prescindir de $Env:PSModulePath, siempre es posible importar el módulo manualmente, especificando la ruta completa al applet en el comando Import-Module. Puede consultar el contenido de la variable $Env:PSModulePath con el siguiente comando:
PS > $Env:PSModulePath.Split(';')
C:\Users\Nicol\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
Una vez encontrada la ubicación, basta con crear una carpeta con el nombre del módulo y, a continuación, un archivo PSM1. Debe tener el mismo nombre que la carpeta. Este archivo contendrá el código PowerShell, e incluso puede llamar a scripts PS1.
Ejemplo de creación de un módulo
PS > New-Item -Path $Home\Documents\WindowsPowerShell\Modules `
-Name MyModuleTools -Type directory
PS > New-Item -Name MyModuleTools.psm1 -Type File `
-Path $Home\Documents\WindowsPowerShell\Modules\MyModuleTools
Por el momento, el módulo está vacío. A continuación, añadiremos algunas funciones útiles. También es una buena idea incluir una función que llame a una segunda función bastante larga que se utiliza regularmente.
Los usuarios de Bash en Linux suelen crear alias para definir comportamientos preestablecidos de ciertos comandos. En PowerShell, los alias no se utilizan de esta manera. Es necesario declarar una nueva función que actuará como alias y llamará a la función o comando que quieres acortar. Estas...
Manifiesto de módulo
El manifiesto de un módulo es un elemento importante si quieres compartir tu trabajo. Es un archivo en formato PSD1. Está estructurado como una tabla hash (hashtable), donde cada campo contiene metadatos sobre el módulo. Estos metadatos agrupan una serie de elementos sobre el módulo, como el nombre del autor, el número de versión, las notas de publicación, los diferentes archivos que se deben cargar y los diferentes requisitos previos del módulo. Esta última sección no es meramente informativa. Tiene un impacto importante cuando se carga el módulo.
Si se especifica una versión mínima de PowerShell en el manifiesto, el módulo no podrá utilizarse si la versión de PowerShell que ejecuta el sistema es anterior a la especificada.
PowerShell incluye dos cmdlets principales para trabajar con manifiestos: New-ModuleManifest, que permite crearlos, y Test-ModuleManifest, que verifica su validez.
1. Creación del manifiesto
El cmdlet New-ModuleManifest tiene un gran número de parámetros. Esto se debe a que cada parámetro corresponde a un campo de la tabla hash definida en el manifiesto. Solo el parámetro -Path es obligatorio. Si no se especifican otros parámetros, el archivo generado incluirá por defecto todos los campos necesarios.
Parámetros del cmdlet :
Parámetro |
Descripción |
AliasToExport |
Lista de alias que deben exportarse para que el usuario pueda utilizarlos. |
Author |
Autor del módulo. |
ClrVersion |
Versión del CLR utilizada por el módulo. Esta información está contenida en la variable $PSVersionTable. |
CmdletsToExport |
Lista de cmdlets que se exportarán para que el usuario pueda utilizarlos. |
CompanyName |
Nombre de la empresa del autor. |
Copyright |
Copyright por los que se rige el módulo. |
DefaultCommandPrefix |
Prefijo que se antepone a cada comando para evitar conflictos con otros módulos que contienen comandos con el mismo nombre. El prefijo se coloca antes del nombre del comando, no antes del verbo. |
Description |
Descripción del módulo. |
DotNetFrameworkVersion |
Versión mínima del framework del entorno .NET Framework necesaria para ejecutar el módulo. |
DscResourcesToExport |
Lista de recursos DSC contenidos en el módulo, para ser exportados. |
FileList |
Inventario de archivos... |
Exportación de los miembros de un módulo
1. El comando Export-ModuleMember
Por defecto, con o sin manifiesto, un módulo contenido en un archivo PSM1 exporta todas sus funciones. Sin embargo, las variables y los alias no se exportan, a pesar de la presencia de los campos VariablesToExport y AliasToExport en el manifiesto.
Por esta razón, puede ser útil utilizar el cmdlet Export-ModuleMember. Solo puede utilizarse en dos casos: en un módulo dinámico o en un archivo PSM1. El comando solo tiene cuatro parámetros: -Function, -Alias, -Cmdlet, -Variable. Cada parámetro acepta una matriz de cadenas de caracteres ([String[]]).
En cuanto se utiliza el comando Export-ModuleMember, todos los elementos que se deseen exportar deben indicarse explícitamente. Por ello, debe tener cuidado al añadir un elemento a su módulo.
Ejemplo de declaración
Function Get-PSSerialNumber {
(Get-WMIObject -Class Win32_Bios).SerialNumber
}
Function Get-PSFolderSize {
Param(
[ValidateScript({Test-Path $_})]
[String]$Path
)
(Get-ChildItem -Path $Path -Recurse -File | `
Measure-Object -Property Length -Sum ).Sum /1MB
}
Set-Alias -Name gpsn -Value 'Get-PSSerialNumber'
$ScriptAuthor = 'Nicolas Baudin'
Export-ModuleMember -Function `
'Get-PSFolderSize','Get-PSSerialNumber'
Export-ModuleMember -Variable 'ScriptAuthor' -Alias 'gpsn'
Una vez importado el módulo, es posible utilizar alias y funciones, pero también acceder a la variable $ScriptAuthor.
2. Comportamiento específico
Existen diferentes formas de exportar los miembros de un módulo. En esta sección se analizará cada tipo de miembro por separado.
El comportamiento puede variar en función de la versión de PowerShell. A continuación, se muestra la versión utilizada en los siguientes casos:
PS > $PSVersionTable ...
Estructura multiarchivo
A la hora de mantener y desarrollar un módulo, su estructura es un punto importante. Si está muy mal organizado, nadie querrá trabajar en él, ni siquiera utilizarlo. En cambio, si la estructura está clara y definida, a la gente le gustará participar en su ciclo de vida.
Realmente no existe una estructura convencional. Lo más importante es documentar la finalidad de cada carpeta y archivo. Esto facilitará mucho el trabajo de un corrector o colaborador.
La estructura que se muestra aquí es un ejemplo. No es perfecta, pero tiene grandes ventajas a la hora de facilitar el mantenimiento de un módulo.
Estructura jerárquica
$Env:PSModulePath
└─<Versión>
└─<Nombre del módulo>
├─Public
└─<Nombre Script>.ps1
├─Private
└─<Nombre de script>.ps1
├─<Manifiesto del módulo>.psd1
├─<Archivo principal>.psm1
└─<other files>
El módulo consta...
Pasar a Build con Sampler
La filosofía de desarrollo de un paquete suele incluir una fase de construcción (build). Esta fase toma el código fuente y lo organiza para generar el paquete que luego se desplegará. Esta fase de build suele incluir con frecuencia la compilación del código.
En nuestro caso, se trata de un módulo. El objetivo es poder combinar la estructura vista anteriormente con la ventaja de un archivo PSM1 completo y de alto rendimiento. Para ello, partimos de una estructura multiarchivo, similar a la presentada en el apartado anterior, para el desarrollo del módulo. A continuación, se utiliza una herramienta de compilación para crear un módulo construido sobre un único PSM1. La herramienta presentada aquí es Sampler. Es un módulo comunitario desarrollado por Gael Colas. Existen otras herramientas similares, como Stucco.
La principal motivación de Gael para diseñar este módulo fueron los recursos DSC. De hecho, Gael es uno de los miembros fundamentales de la comunidad DSC y quería normalizar la redacción de recursos DSC basando su desarrollo en una estructura y unos procesos de validación y despliegue comunes.
Sampler utiliza una serie de módulos para construir un módulo de principio a fin. He aquí algunos de ellos:
-
Plaster: genera la estructura del nuevo módulo a partir de plantillas.
-
InvokeBuild: organiza un conjunto de acciones en forma de task.
-
PSDepend: gestiona las dependencias para construir el módulo.
-
PSDeploy: gestiona el despliegue del módulo en una galería interna o externa.
El módulo Sampler está disponible en la PowerShell Gallery. El módulo se instala mediante el módulo PowerShellGet. Para obtener más información sobre el uso de este módulo, consulte el capítulo Gestión de módulos y paquetes.
PS > Install-Module Sampler
1. Creación de un módulo sencillo
Sampler ofrece varias plantillas de estructura para crear módulos:
-
SimpleModule: proyecto de módulo simple con una estructura y un proceso de automatización mínimos.
-
SimpleModule_NoBuild: proyecto de módulo simple sin estructura de automatización.
-
CompleteSample: proyecto de módulo completo con todos los ejemplos.
-
Dsccommunity: proyecto...