PowerShell: ¿cómo ejecutar comandos y scripts de forma remota con Invoke-Command?
Table of Contents
I. Presentación
La administración remota es una práctica común que debería fomentarse para mejorar la eficiencia de los administradores de sistemas y redes. PowerShell ofrece una serie de opciones que permiten al administrador ejecutar comandos o scripts de forma remota en un conjunto de máquinas. Estos pueden ser estaciones de trabajo o servidores, según sea necesario.
Entre las opciones posibles se incluye el cmdlet de PowerShell denominado Invoke-Command
. Se utiliza para ejecutar un comando o script en uno o varios ordenadores remotos, a través de la aplicación WinRM o SSH en función del contexto.
También se pueden utilizar los dos métodos siguientes:
- Utilizar una sesión remota de PowerShell, a través de las etiquetas
New-PSSession
yEnter-PSSession
- Utilice la
-ComputerName
ciertos cmdlets para apuntar directamente a una máquina remota
En este tutorial, sólo exploraremos el uso del cmdlet Invoke-Command
para ejecutar comandos remotos en varias máquinas. Para obtener más información, consulte este artículo anterior :
II. Requisitos para la ejecución remota
Antes de usar Invoke-Command
, es esencial asegurarse de que el entorno está configurado correctamente. Aquí utilizaremos la configuración más sencilla para no cargar el artículo con la configuración de WinRM, a saber: ejecutar comandos entre varias máquinas integradas en un dominio de Active Directory, lo que facilita la autenticación y la aprobación mutua de los hosts.
WinRM está asociado a la funcionalidad de gestión remota de Windows. El estado por defecto es :
- En Windows Server, la Gestión Remota está activada por defecto, lo que significa que WinRM está escuchando.
- En Windows 10 y Windows 11, la Gestión remota está desactivada por defecto, por lo que no es posible conectarse a una estación de trabajo remota sin configurarla.
Para activar WinRM (Windows Remote Management) en una máquina, basta con ejecutar este comando :
Enable-PSRemoting
Este comando activa WinRM, que iniciará el servicio asociado, escuchará en el puerto 5985/TCP (HTTP) y configurará el cortafuegos para permitir conexiones remotas. Para configurar WinRM en un grupo de máquinas, siga este tutorial :
Puede utilizar este comando para determinar si el servicio WinRM se está ejecutando o no en un equipo remoto (adaptando el nombre del host de destino):
Test-WSMan -ComputerName W11-01.it-connect.local
III. Uso del comando Invocar
Una vez configurado el entorno, Invoke-Command
puede utilizarse para ejecutar comandos remotos. En el resto de este artículo, veremos varios ejemplos de cómo se puede utilizar. Antes de empezar, este comando puede :
- Ejecutar un bloque de código que contenga uno o varios comandos mediante la función
-ScriptBlock
- Ejecutar un script PowerShell (.ps1) utilizando el parámetro
-FilePath
A. Ejecutar un único comando
Ejecutar un comando en un ordenador remoto llamado W11-01.it-connect.local es como sigue:
Invoke-Command -ComputerName W11-01.it-connect.local -ScriptBlock { Get-Process }
Este comando recupera la lista de procesos que se están ejecutando actualmente en la máquina remota, gracias a la ejecución de Get-Process
.

B. Ejecución de un script PowerShell
También es posible ejecutar un script completo especificando un archivo PowerShell en formato PS1. Si la máquina remota no tiene acceso al script a través de la red, esto no supone ningún problema. Lo más importante es que el script sea accesible por la máquina desde la que se creó. Invoke-Command
se ejecuta:
Invoke-Command -ComputerName W11-01.it-connect.local -FilePath "C:\Scripts\MonScript.ps1"

Esto permite automatizar tareas en varias máquinas, ya sean estaciones de trabajo o servidores.
Nota: para ejecutar el comando o script en segundo plano como un trabajo, añada el parámetro -AsJob.
Si el script que se va a ejecutar ya se encuentra en el equipo remoto y no se puede acceder a él desde el equipo de origen, utilice esta sintaxis :
Invoke-Command -ComputerName W11-01.it-connect.local -ScriptBlock { C:\Scripts\MonScript.ps1 }
C. Ejecutar un comando en varias máquinas
Para ejecutar un comando en varias máquinas, basta con especificar varios nombres de host separados por una coma. He aquí un ejemplo de cómo reiniciar el servicio Print Spooler en 2 máquinas diferentes:
Invoke-Command -ComputerName W11-01.it-connect.local,W11-02.it-connect.local -ScriptBlock { Restart-Service -Name Spooler }
Personalmente, prefiero almacenar la lista de máquinas en un array y llamar a la variable mediante Invoke-Command
. También es más práctico si tiene varios comandos para ejecutar a través de diferentes llamadas a Invoke-Command
.
$ComputersList = @("W11-01.it-connect.local","W11-02.it-connect.local")
Invoke-Command -ComputerName $ComputersList -ScriptBlock { Restart-Service -Name Spooler }
Esto simplifica la gestión de varias máquinas. He aquí otro ejemplo de cómo reiniciar un conjunto de máquinas de forma remota:
Invoke-Command -ComputerName $ComputersList -ScriptBlock { Restart-Computer -Force }
También podríamos recuperar una lista de ordenadores dinámicamente desde el Directorio Activo, y luego realizar una acción en cada máquina de esta lista.
# Obtener la lista de ordenadores de l'OU "OU=PC,OU=IT-Connect,DC=it-connect,DC=local"
$ComputersListAD = (Get-ADComputer -Filter * -SearchBase "OU=PC,OU=IT-Connect,DC=it-connect,DC=local").DNSHostName
# Obtener el espacio de disco disponible en cada máquina de la lista
Invoke-Command -ComputerName $ComputersListAD -ScriptBlock { Get-CimInstance -Class Win32_LogicalDisk | Select-Object -Property DeviceID, Name, @{
label='UsedSpace'
expression={(($_.Size - $_.FreeSpace)/1GB).ToString('F2')}
} }
Aquí utilizamos el parámetro -ScriptBlock
, pero es perfectamente posible ejecutar un script siguiendo el mismo principio mediante el parámetro -FilePath
.
D. Especificar identificadores
Si el usuario actual no tiene los derechos necesarios, es posible proporcionar identificadores añadiendo el parámetro -Credential
. Espera el valor de un objeto PSCredential
con un nombre de usuario y una contraseña, que podemos generar mediante Get-Credential
:
$Identifiants = Get-Credential
Invoke-Command -ComputerName W11-01.it-connect.local -Credential $Identifiants -ScriptBlock { Get-Service }
Esto garantiza que la ejecución tenga lugar con los permisos del usuario especificado; de lo contrario, se utilizará el usuario actual de la sesión de PowerShell.

E. Utilizar una sesión persistente
Otra forma de hacerlo, en lugar de utilizar -Credential
y -ComputerName
es utilizar una sesión WinRM (persistente) o una conexión SSH. En el primer caso, es necesario crear una nueva sesión a través de New-PSSession
y utilizar el parámetro -Session
mientras que para el segundo caso, el parámetro -SSHConnection
debe especificarse.
Por ejemplo:
$MaSession = New-PSSession -ComputerName W11-01.it-connect.local -Credential IT-Connect\admin.pc
Invoke-Command -Session $MaSession -ScriptBlock { Restart-Computer -Force }
Cuando utilice -ComputerName
PowerShell creará una sesión para ejecutar el comando y luego cerrará la sesión al mismo tiempo. Si necesita compartir datos entre varios comandos que se ejecutan de forma independiente, debe utilizar una sesión persistente, como en el ejemplo anterior. Este método tiene la ventaja de mantener los datos en la misma sesión hasta que se cierre.
F. Uso de argumentos
Puede utilizar argumentos para pasar valores o variables entre la máquina local y la máquina remota. Para ello se utiliza el método -ArgumentList
y la variable especial $Args
.
En el ejemplo siguiente, la variable $ServiceName
se define en la máquina local. Su valor se transmite a la máquina remota mediante el parámetro -ArgumentList
y este valor se utiliza cuando el comando se ejecuta a través de la función $args[0]
. Como puede haber varios argumentos (separados por una coma), se genera una matriz cuyo primer valor se almacena en el índice 0.
$ServiceName = "winrm"
Invoke-Command -ComputerName $ComputersList -ScriptBlock { Get-Service $args[0] } -ArgumentList $ServiceName
La imagen siguiente ilustra cómo funciona.

IV. Conclusión
Invoke-Command
es un comando esencial para administrar máquinas remotas a través de PowerShell, ya sea para ejecutar un único comando o un script completo. Gracias a este mecanismo, puedes optimizar la gestión de tu infraestructura y mejorar la eficiencia.
Para obtener más información sobre PowerShell, consulte mi curso en línea y mi libro :
- Libro de Florian Burnel - Introducción a PowerShell
- Curso en línea - Introducción a PowerShell