Instalando programas en clientes remotos usando PowerShell

Quizá algunos me digan que eso no es necesario. Que es mejor ir y hacer la instalación de forma manual y que así hacen algo de ejercicios y demás. Bueno, no es mi caso y creo que tampoco será el caso de los que tienen la necesidad de implementar un software (mi caso con el Nextcloud y es lo que voy a usar de Ejemplo) en una entidad donde existen una X cantidad de dispositivos. Y hacer lo mismo 3 veces no cansa, pero cuando llegas a 50 ya no te parece una buena idea. Para estas cosas existen los scripts. Y vamos a darle crédito a Microsoft, con Batch no se llegaba muy lejos, con Visual Basic Script ya hacías muchas cosas, pero con PowerShell sí se puede lograr.

Vamos a empezar, lo primero, es tener en cuenta que tanto el host donde corre el script, como la PC destino tienen que tener PowerShell instalado. Esto ya viene por defecto en Windows 10 así que no creo que sea un problema a menos que las PC sean muy viejas. Para esos casos, ya tendremos otro tutorial.

Lo segundo es habilitar los hosts de confianza. Pasa lo siguiente: Si intentas hacer una sesión en PowerShell a un equipo remoto, te pedirá HTTPS o que los equipos sean de confianza. Para este tutorial, vamos a trabajar con equipos de confianza y evitaremos todo el trabajo de un certificado SSL Valido (ya hay tutoriales aquí sobre el tema)

Vean como se le pasan todas las variables a la consola y cuando se ejecuta la sesión, pues da un error. El error es el siguiente:

New-PSSession : [192.168.24.2] Connecting to remote server 192.168.24.2 failed with the following error message : The WinRM client cannot process the request.
Default authentication may be used with an IP address under the following conditions: the transport is HTTPS or the destination is in the TrustedHosts list, and
explicit credentials are provided. Use winrm.cmd to configure TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated. For more
information on how to set TrustedHosts run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
At line:1 char:13
+ $Session1 = New-PSSession -ComputerName $computer -Credential $Creden …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme….RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : CannotUseIPAddress,PSSessionOpenFailed

En el host (PC desde donde vamos a mandar a ejecutar el script) vamos a agregar los hosts de confianza, que es a los cuales nos vamos a poder conectar de forma insegura.

Set-Item WSMan:localhost\client\trustedhosts -value "192.168.24.2"

Con esto, agregamos el host 192.168.24.2 como destino (vean que es la misma consola que antes dio el error). Si esto les resulta un poco tedioso, pueden poner un * en lugar de «192.168.24.2» y automáticamente permiten cualquier host como destino. (Eso fue lo que yo hice, pero no quiere decir que sea lo más seguro). Podemos ver los hosts configurados de la siguiente forma:

 Get-Item WSMan:localhost\client\TrustedHosts


Ahora si podemos probar que podamos usar una sesión de PowerShell Remota

#usuario y password dominio
$UsuarioDominio = 'Administrator'
$PasswordDominio = Read-Host -Prompt "Tu Password:" -AsSecureString 
$CredencialesDominio = New-Object System.Management.Automation.PSCredential ($UsuarioDominio, $PasswordDominio)
$RemoteComputers=@("192.168.24.2", "192.168.24.3", "192.168.24.4"

foreach ($computer in $RemoteComputers) {

    # Creamos la sesión remota.
    $Session1 = New-PSSession -ComputerName $computer -Credential $CredencialesDominio
}

En este momento para ejecutar esto, deben abrir «PowerShell ISE» que es un IDE integrado para PowerShell, crean un archivo nuevo y pegan el código. Luego de esto, le puedan dar ejecutar con F5.

Vean como en este caso, no devuelve nada, porque no hay ningún comando, solo las sesiones. Ahora veamos las sesiones que están abiertas

Esto lo logramos con el comando

 Get-PSSession

Ahora que ya sabemos que funciona, vamos a limpiar las sesiones y hablar un poco de los problemas que vamos a tener en el proceso. Por partes:

Get-PSSession | Remove-PSSession

Esto nos permite conectar la salida del primer comando con el segundo. El caso de Remove-PSSession lleva el identificador de nuestra sesión, por ejemplo 20. Pero como antes le estamos diciendo que el id que va a usar es el que está saliendo de la consulta Get-PSSession.

Ahora hablemos de las variables, en el caso de las Sesiones remotas en PowerShell, las variables se declaran en una sesión y no estarán disponibles cuando enviemos los comandos a la sesión remota. Así que, por el momento, vamos a declararlas dobles (más adelante prometo editar cuando encuentre una forma más optima de hacerlo)

Ahora sí. Vamos a ver el script.

#Ordenadores separados por comas...
$RemoteComputers = @("192.168.24.5")

##################
#Variables a usar#
##################

#Carpeta remota en el cliente (si no existe se creará)
$install_folder='c:\test2'

#Carpeta del servidor donde está el programa o los programas a instalar
$local_folder="C:\PRECAM\Programas\"

#App a instalar en el cliente (pueden ser varias y solo duplican el procedimiento debajo
$app_to_install="Nextcloud-3.0.1-setup.exe"

#usuario y password dominio
$UsuarioDominio = 'Administrator'
$PasswordDominio = Read-Host -Prompt "Tu Password:" -AsSecureString 
#Almacenamiento de credenciales en PS
$CredencialesDominio = New-Object System.Management.Automation.PSCredential ($UsuarioDominio, $PasswordDominio)

#Recorremos el listado de equipos para efectuar el procedimiento en cada una
foreach ($computer in $RemoteComputers) {
    # Creamos la session remota.
    $Session1 = New-PSSession -ComputerName $computer -Credential $CredencialesDominio
    
    #este comando abre una conexión usando la sesión anterior
    #Que permite ejecutar comandos en el cliente
    Invoke-Command -Session $Session1 -ScriptBlock { 
    #Las variables declaradas arriba están en la sesión actual,
    #Por tanto en la sesión remota no existen. Esta es la forma que encontré de mandarlas
    #Si encuentran otra por favor en los comentarios déjalo
    #Aquí tenemos que volver a declarar la variable de la carpeta del servidor
    $remote_folder = 'c:\test2'
    #Enviamos la variable a la sesión remota
    Get-WinEvent $remote_folder
    #Creamos la carpeta donde vamos a alojar el programa en el cliente
    New-Item -type directory -force -Path $remote_folder
    }
    
    # Copiamos el instalador al equipo remoto.
    #Vean que en este caso uso $install_folder y no $remote_folder porque $remote_folderno existe aqui
    Copy-Item "$($local_folder)$($app_to_install)" -Destination $install_folder -ToSession $Session1 -Recurse -Force

    
    #Volvemos a abrir la conexión de ejecución de comandos en el cliente:
    Invoke-Command -Session $Session1 -ScriptBlock { 
        
        #Declaramos de nuevo la app que vamos a instalar
        #Puesto que necesitamos trabajar con ella en el cliente
        #Arriba las llame distintas para que se vea la diferencia, pero pueden llamarse igual
        $app_to_install="Nextcloud-3.0.1-setup.exe"
          
        #Envío de la variable de la app a instalar
        Get-WinEvent $app_to_install

        # Creamos el BAT. Es necesario de esta forma para evitar el bloqueo del archivo EXE 
        #si es ejecutado directamente.
        #El archivo .bat solo tendrá la aplicación y el parámetro /S que en windows 
        #se usa para instalar en modo silcencioso
        Set-Content "$($remote_folder)\instalame.bat" -value "$($remote_folder)\$($app_to_install) /S"

        # Ejecutamos el BAT, que a su vez ejecuta el instalador de la App y espera a que termine.
        Start-Process "$($remote_folder)\instalame.bat" -Wait

        #Borramos lo copiado en el cliente. "Aquí no ha pasado nada"
        cmd /c "rd /S /Q $($remote_folder)"

   } #Final Invoke-Command
   
    # Borramos todas las sesiones como ya vimos
    Get-PSSession | Remove-PSSession


    #Creamos un registro para que nos informe de lo ocurrido.
    #Pueden usar tanto la unidad que quieran como el nombre...
    Out-File -FilePath c:\Soft_Instalado_Remoto.txt -Append -InputObject "$($app_to_install) - $computer"
} #Fin del foreach

Siempre recuerden que un script no es una solución única, así que siéntanse libres de modificar este en los comentarios y dejar sus alternativas. Sobre todo, en la parte de las variables.

 

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en una estrella para puntuar!

Promedio de puntuación 5 / 5. Recuento de votos: 8

Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.

Sé el primero en comentar

Dejar una contestacion

Tu dirección de correo electrónico no será publicada.


*