Búsqueda de sitios web

Llame al script de PowerShell desde otro script [4 formas]


1. Introducción al planteamiento del problema

PowerShell, un potente lenguaje de secuencias de comandos y shell de línea de comandos, se utiliza ampliamente para la automatización en entornos Windows. Un requisito común en las secuencias de comandos de PowerShell es llamar una secuencia de comandos desde otra, lo que permite la programación modular y la reutilización del código.

Supongamos que tenemos dos scripts:

  • ChildScript.ps1: este script realiza una tarea y devuelve un valor. Por ejemplo, podría comprobar el espacio en disco y devolver verdadero si hay suficiente espacio o falso en caso contrario.
  • MainScript.ps1: este script llama a ChildScript.ps1 y realiza acciones basadas en el valor devuelto por ChildScript.ps1.

2. ChildScript.ps1

ChildScript.ps1:

# ChildScript.ps1

# Function to check disk space
function Check-DiskSpace {
    # Example condition: If free space is more than 10GB
    $freeSpace = Get-PSDrive C | Select-Object -ExpandProperty Free
    return $freeSpace -gt 10GB
}

# Calling the function and returning its output
Check-DiskSpace

Escribamos un script principal diferente según los diferentes métodos que vamos a utilizar.

3. Uso del operador & (operador de llamada)

El método más sencillo es utilizar el operador &, también conocido como operador de llamada, en PowerShell.

MainScript.ps1 (Uso y Operador):

# MainScript.ps1

# Path to the child script
$childScriptPath = ".\ChildScript.ps1"

# Calling the child script and capturing the output
$isEnoughSpace = & $childScriptPath

# Making a decision based on the output
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available."
} else {
    Write-Host "Warning: Low disk space."
}

Explicación:

  • Configuración de la ruta al script secundario: el script establece $childScriptPath con la ruta relativa a ChildScript.ps1.
  • Llamar al script secundario: utiliza el operador de llamada (&) para ejecutar ChildScript.ps1 y captura su salida (se espera que sea un valor booleano). ) en la variable $isEnoughSpace.
  • Decisión basada en el resultado: una declaración if-else verifica el valor de $isEnoughSpace. Si es $true, el script imprime "Espacio en disco suficiente disponible". De lo contrario, imprime "Advertencia: Poco espacio en disco".

Este script demuestra cómo llamar a un script de PowerShell independiente y utilizar su salida para la lógica condicional dentro del script de llamada.

Rendimiento:

Este método es eficiente y tiene una sobrecarga de rendimiento mínima. Es una llamada directa y ejecuta el script en la sesión actual de PowerShell.

4. Uso de abastecimiento de puntos

El abastecimiento de puntos es una técnica en PowerShell para ejecutar un script en el alcance actual, lo que permite que el script principal acceda a variables y funciones definidas en el script secundario.

MainScript.ps1 (usando abastecimiento de puntos):

# MainScript.ps1

# Path to the child script
$childScriptPath = ".\ChildScript.ps1"

# Dot sourcing the child script
. $childScriptPath

# Since the function is now available in the main script's scope, it can be called directly
$isEnoughSpace = Check-DiskSpace

# Decision based on the output
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available."
} else {
    Write-Host "Warning: Low disk space."
}

Este script, MainScript.ps1, demuestra cómo usar el origen de puntos en PowerShell para llamar a una función desde otro script (ChildScript.ps1) y usar su salida para la toma de decisiones:

  1. Configuración de la ruta al script secundario: a la variable $childScriptPath se le asigna la ruta relativa a ChildScript.ps1.
  2. Fuente de puntos del script secundario: el operador de origen de puntos (.) se utiliza para ejecutar ChildScript.ps1. Esto hace que todas las funciones y variables de ChildScript.ps1 estén disponibles en el alcance de MainScript.ps1.
  3. Llamar a la función directamente: la función Check-DiskSpace de ChildScript.ps1 se llama directamente y su salida (se espera que sea un disco indicador booleano) estado del espacio) se almacena en $isEnoughSpace.
  4. Tomar una decisión basada en el resultado: el script utiliza una declaración if-else para verificar $isEnoughSpace. Si es $true, indica suficiente espacio en disco e imprime "Suficiente espacio en disco disponible". De lo contrario, imprime "Advertencia: Poco espacio en disco".

Este enfoque es útil cuando queremos acceder a funciones o variables de otro script directamente dentro del alcance del script actual.

Rendimiento:

El abastecimiento de puntos es eficiente y particularmente útil cuando el script principal necesita acceder a recursos definidos en el script secundario. Tiene características de rendimiento similares a las del operador de llamadas.

5. Uso de expresión de invocación

Otro método consiste en utilizar el cmdlet Invoke-Expression, que evalúa una cadena como código de PowerShell y la ejecuta.

MainScript.ps1 (Usando la expresión Invocar):

# MainScript.ps1

# Path to the child script
$childScriptPath = ".\ChildScript.ps1"

# Calling the child script and capturing the output using Invoke-Expression
$isEnoughSpace = Invoke-Expression $childScriptPath

# Making a decision based on the output
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available."
} else {
    Write-Host "Warning: Low disk space."
}

Explicación: Invoke-Expression evalúa el script en la ruta especificada como un comando de PowerShell. La salida del script secundario se captura en $isEnoughSpace, que luego se utiliza para tomar una decisión.

Rendimiento:

Invoke-Expression tiene una ligera sobrecarga al analizar la expresión de cadena, pero esto generalmente es insignificante. Es tan eficiente como el operador de llamadas para la mayoría de los propósitos prácticos.

6. Usando el proceso de inicio

Para ejecutar scripts de forma completamente independiente, se puede utilizar Start-Process. Para Start-Process, es importante tener en cuenta que inicia un proceso separado, lo que hace que capturar la salida directamente sea más complejo. Para capturar la salida, normalmente redirigiríamos la salida a un archivo y luego leer desde ese archivo.

MainScript.ps1 (usando el proceso de inicio):

# MainScript.ps1

# Path to the child script
$childScriptPath = ".\ChildScript.ps1"
$outputFile = ".\output.txt"

# Starting the child script as a separate process and redirecting output to a file
Start-Process PowerShell -ArgumentList "-File `"$childScriptPath`" > `"$outputFile`"" -Wait -NoNewWindow

# Reading output from the file
$isEnoughSpace = Get-Content $outputFile -Raw

# Making a decision based on the output
if ($isEnoughSpace -eq $true) {
    Write-Host "Sufficient disk space available."
} else {
    Write-Host "Warning: Low disk space."
}

# Optionally, delete the output file if it's no longer needed
Remove-Item $outputFile

Explicación: Start-Process se usa para ejecutar ChildScript.ps1 en un proceso de PowerShell separado. La salida se redirige a un archivo temporal (output.txt). Luego, el script principal lee el contenido de este archivo para capturar el resultado del script secundario. Después de procesar la salida, el archivo temporal se elimina para su limpieza.

Este método es útil para aislar completamente el script secundario, ejecutándolo en un proceso separado. Esto puede resultar beneficioso para scripts que consumen muchos recursos o scripts que deben ejecutarse en un contexto diferente.

Rendimiento:

Ejecutar un script como un proceso separado introduce una sobrecarga adicional en comparación con otros métodos. Es más lento debido a la creación de un nuevo proceso pero proporciona aislamiento y es útil cuando dicha separación es necesaria.

7. Llamar al script de PowerShell con parámetros de otro script

En las secuencias de comandos avanzadas de PowerShell, es común no solo llamar a una secuencia de comandos desde otra sino también pasar parámetros a la secuencia de comandos llamada. Este enfoque mejora la flexibilidad del script y permite la ejecución dinámica basada en diferentes entradas.

Escenario: Continuando con nuestro ejemplo anterior, digamos que ChildScript.ps1 ahora acepta un parámetro para especificar la unidad para verificar el espacio en disco. MainScript.ps1 necesita llamar a ChildScript.ps1 con una letra de unidad específica como parámetro y luego actuar en función del valor devuelto.

Objetivo: exploraremos métodos para llamar a ChildScript.ps1 con un parámetro de MainScript.ps1, capturaremos el resultado y lo usaremos en MainScript.ps1 para realizar más acciones.

ChildScript.ps1:

# ChildScript.ps1

param (
    [string]$DriveLetter
)

function Check-DiskSpace {
    param (
        [string]$Drive
    )
    $freeSpace = Get-PSDrive $Drive | Select-Object -ExpandProperty Free
    return $freeSpace -gt 10GB
}

Check-DiskSpace -Drive $DriveLetter

Explicación: ChildScript.ps1 ahora acepta un parámetro $DriveLetter. La función Check-DiskSpace utiliza este parámetro para verificar el espacio en disco de la unidad especificada.

Usemos diferentes métodos para llamar al script de PowerShell con parámetros de otro script:

7.1 Uso del operador de llamada (&) con parámetros:

MainScript.ps1 (Uso y operador):

# Using the Call Operator with Parameters

$childScriptPath = ".\ChildScript.ps1"
$drive = "C"
$isEnoughSpace = & $childScriptPath -DriveLetter $drive
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available on drive $drive."
} else {
    Write-Host "Warning: Low disk space on drive $drive."
}

7.2 Uso de Dot Sourcing con parámetros:

MainScript.ps1 (uso de abastecimiento de puntos con parámetros):

# Using Dot Sourcing with Parameters

. $childScriptPath -DriveLetter $drive
$isEnoughSpace = Check-DiskSpace -Drive $drive
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available on drive $drive."
} else {
    Write-Host "Warning: Low disk space on drive $drive."
}

7.3 Uso de Invoke-Expression con parámetros:

MainScript.ps1 (Usando Invoke-Expression con parámetros):

# Using Invoke-Expression with Parameters

$scriptWithParams = "$childScriptPath -DriveLetter $drive"
$isEnoughSpace = Invoke-Expression $scriptWithParams
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available on drive $drive."
} else {
    Write-Host "Warning: Low disk space on drive $drive."
}

7.4 Uso del proceso de inicio con parámetros:

MainScript.ps1 (Usando el proceso de inicio con parámetros):

# Using Start-Process with Parameters

$outputFile = ".\output.txt"
$argumentList = "-File `"$childScriptPath`" -DriveLetter $drive > `"$outputFile`""
Start-Process PowerShell -ArgumentList $argumentList -Wait -NoNewWindow
$isEnoughSpace = Get-Content $outputFile -Raw
if ($isEnoughSpace) {
    Write-Host "Sufficient disk space available on drive $drive."
} else {
    Write-Host "Warning: Low disk space on drive $drive."
}

Remove-Item $outputFile

8. Pasar objetos complejos como parámetro

Pasar objetos complejos como parámetros directamente entre scripts de PowerShell es un desafío inherente debido a la naturaleza de cómo los scripts y los procesos manejan los datos. Sin embargo, existen algunos métodos y soluciones a considerar:

8.1. Abastecimiento de puntos

El abastecimiento de puntos es un método que se puede utilizar cuando los scripts se ejecutan en el mismo contexto. No inicia un nuevo proceso, sino que ejecuta el script en la sesión actual de PowerShell.

  • Uso: si obtenemos un script secundario como fuente puntual, se ejecuta en el contexto del script de llamada. Esto permite el acceso compartido de objetos complejos definidos en un script a otro.
  • Limitación: esto solo funciona cuando los scripts se ejecutan en la misma sesión de PowerShell. No es adecuado para escenarios que requieren que los scripts se ejecuten en entornos aislados.

8.2. Variables basadas en sesiones

En PowerShell, podemos crear variables basadas en sesiones que pueden almacenar objetos complejos. Se puede acceder a estas variables en scripts que se ejecutan en la misma sesión.

  • Uso: defina una variable de sesión en un script y acceda a ella en otro script.
  • Limitación: similar al abastecimiento de puntos, este método solo funciona dentro de la misma sesión de PowerShell.

8.3. Serialización y deserialización

Para pasar datos entre scripts que se ejecutan en diferentes contextos (por ejemplo, diferentes procesos), la serialización es el método más viable. Serializamos un objeto en un formato de cadena como JSON o XML, pasamos la cadena al otro script y luego lo deserializamos nuevamente a un objeto.

  • Uso: Utilice ConvertTo-Json y ConvertFrom-Json o Export-Clixml e Import-Clixml para convertir objetos hacia y desde cadenas.
  • Limitación: Es posible que la serialización no preserve perfectamente algunos tipos de objetos y existe una sobrecarga al serializar y deserializar objetos.

8.4. Almacenamiento temporal de archivos

Almacenar objetos en archivos temporales es otra forma de compartir datos complejos entre scripts. Este es un enfoque más manual pero puede resultar efectivo para ciertos tipos de objetos.

  • Uso: almacene el objeto en un archivo temporal en un script y léalo desde el otro script.
  • Limitación: requiere administrar archivos temporales y garantizar que se creen de forma segura y se eliminen correctamente después de su uso.

8.5. Comunicación entre procesos (IPC)

Para escenarios avanzados, se pueden utilizar mecanismos IPC como canalizaciones con nombre o archivos mapeados en memoria para pasar objetos complejos entre scripts.

  • Uso: Establecer un canal IPC para transmitir datos entre procesos.
  • Limitación: este enfoque es complejo y puede resultar excesivo para necesidades de secuencias de comandos más simples.

9. Conclusión

Hay varias formas de llamar a un script de PowerShell desde otro script, cada una con diferentes casos de uso e implicaciones de rendimiento:

  • Uso del operador de llamada (&): lo mejor para llamadas de script de propósito general. Es simple, eficiente y ejecuta el script en la sesión actual.
  • Uso de Invoke-Expression: ofrece flexibilidad, pero debe usarse con precaución para evitar riesgos de seguridad.
  • Dot Sourcing (.): ideal para escenarios en los que el script principal necesita acceder a recursos del script secundario.
  • Uso de Start-Process: Adecuado para aislar la ejecución del script secundario del script principal, aunque con cierta sobrecarga de rendimiento.

Al elegir el método correcto, considere los requisitos específicos de nuestro script, como si necesitamos compartir variables y funciones entre scripts, o si necesitamos aislar la ejecución del script. En la mayoría de los casos, el operador de llamadas o el abastecimiento de puntos serán suficientes, ofreciendo un equilibrio entre eficiencia y funcionalidad.

Artículos relacionados