Agilizando la instalación de aplicaciones un 1000% tras instalar Windows limpio o tener tu ordenador de fábrica

24-04-2024

Por Rubén Zamora

Vamos a comenzar explicando una historia, la historia de María.

María es una persona risueña, y amante del sistema MacOS, que es el que utiliza para programar en su día a día, pero ha tenido que cambiar de colaborador y le han dado un nuevo ordenador que usa Windows.

Esto es un “problema” en cierto sentido porque trabajar con Power Shell, en la terminal de Windows, es como empezar de cero para María, ya que a ella le gusta instalar las cosas por gestores de paquetes como brew, que era lo que usaba en MacOS.

Entonces, se pone a buscar información sobre cómo hacer un script en Windows(Power Shell), que le permita preparar su setup inicial de aplicaciones que utiliza para trabajar. Y se pone a ello y acaba creando el siguiente script, que ha decidido dejarlo en un gist de GitHub para que en el ordenador Windows restablecido de fábrica, sólo tenga que abrir una terminal en modo administrador y ejecutar la siguiente línea de comando:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/RubenZagon/1d4931f2547757c3d5ddce75f6b65378/raw/powershell-setup.ps1'))"

Y WUALÁ !! Se comienzan a ejecutar las aplicaciones auto-mágicamente y ésto, le ha reducido a María 2 días de instalación y configuración “de cosas” a 15 minutos.

Antes

instalacion_antes

Después

instalacion_despues

Video demostración de lo que pasa

Requisitos previos

Este script ha sido probado en Windows 11, pero debería poder correr con Windows 10 versión 2004 (build 19041 or higher).

Herramientas que se instalan

Instaladas por scoop

NombreDescripción
scoop-trayHerramienta que permite acceder a la aplicaciones instaladas mediante scoop desde la bandeja del sistema en Windows
curlHerramienta de línea de comandos para transferir datos
busyboxPequeña utilidad que incluye muchos comandos de Unix en un solo ejecutable
fzfUn buscador de archivos y texto para la línea de comandos
vimEditor de texto avanzado
cacertBase de datos de certificados raíz
colortoolHerramienta para aplicar colores a la consola Windows
sudoPermite a los usuarios ejecutar comandos con privilegios de administrador
gpgSistema de cifrado de correo electrónico y archivos
spacesnifferAnaliza el uso del espacio de disco en una partición
sysinternalsConjunto de utilidades para la gestión del sistema
pshazzPermite automatizar tareas con PowerShell y personalizar la experiencia de línea de comandos
mpvReproductor de video de código abierto con una interface de línea de comandos que permite reproducir videos y audio de diversos formatos

Instaladas por WinGet (Mínima instalación)

NombreDescripción
Microsoft.PowerToysConjunto de herramientas de productividad para Windows
PuTTYCliente SSH, Telnet y Rlogin para Windows
WinRARCompresor y descompresor de archivos
SlackAplicación de mensajería para equipos
ZoomAplicación de videoconferencia y reuniones en línea
JetBrains.ToolboxHerramienta de productividad para programadores
BitwardenGestor de contraseñas y autenticación segura
MalwarebytesSoftware antivirus y anti-malware
GreenshotHerramienta para capturar pantallas y editar imágenes
chrisant996.ClinkComplemento para el símbolo del sistema de Windows que mejora la línea de comandos.

Aplicaciones opcionales

NombreDescripción
Google Chrome
Sidekick
Mozilla Firefox
Opera
ObsidianAplicación de notas con enfoque en la estructura y organización
HWMonitorMonitoreo del hardware
BleachBitLimpiador de sistema para Windows
SumatraPDFVisor de PDF de código abierto
SparkCliente de correo electrónico para Mac y iOS
OBS StudioSoftware de transmisión y grabación de video
DBeaverHerramienta de gestión de bases de datos
DiskGeniusHerramienta de gestión de disco
AutoHotkeyLenguaje de scripts para automatización de tareas
RevoUninstallerDesinstalador de software con opciones avanzadas
StarshipUn intérprete de comandos avanzado para el terminal

Instaladas por Chocolately

NombreDescripción
syspinPara fijar las aplicaciones en la barra de tareas del escritorio

Aprendiendo a utilizar la Power Shell

Aquí voy a hacer un análisis un poco por encima de este script - powershell-setup.ps1

Explicación de bloques del script

Aquí pondré una serie de bloques del script que me parecen interesantes analizar, para aprender un par de cosas si se quieren montar sus propios script en power-shell

function Install-ScoopApp { param ( [string]$Package ) Write-Verbose -Message "Preparing to install $Package" if (!(scoop info $Package).Installed) { Write-Verbose -Message "Installing $Package" scoop install $Package } else { Write-Verbose -Message "Package $Package already installed! Skipping..." } }

Esta función verifica si un paquete está instalado, y si no lo está, lo instala. También imprime mensajes detallados usando la opción Write-Verbose, para dar más información sobre el proceso de instalación.

try { Write-Output "Comprobando que winget está bien instalado..." winget --list Write-Output "Okay !" } catch { Start-Sleep -Seconds 5 Write-Error "`nReiniciar el ordenador para que se cojan bien los cambios y comenzar hacer la instalación sin probla" Write-Output "`n`nPor favor, tras reiniciar vuelve a lanzar el script para continuar :)`n`n" Write-Output "Reiniciando en 10 segundos..." Start-Sleep -Seconds 10 Restart-Computer -Force }

Este bloque comprobaría si winget está instalado y funcionando correctamente. Si winget está funcionando, el código escribirá "Okay !" en la consola. Si hay un error al ejecutar el comando winget, porque sigue sin coger las configuraciones tras haberse instalado, el código mostrará un mensaje de error. Luego, esperará 5 segundos antes de reiniciar el ordenador. Después de reiniciar, se espera 10 segundos antes de continuar con la ejecución del script, para que dé tiempo al usuario de informarse de lo que va a pasar.

if ((Get-Command -Name "choco" -CommandType Application -ErrorAction SilentlyContinue)) { # {...bloques de código...} while ($confirmation -eq $null) { $confirmation = Read-Host -Prompt "Lo has entendido bien? ([Y]es/[N]o)?" if ($confirmation -eq "n" -or $confirmation -eq "N") { Write-Host "`nvamos a salir de este modo :)" exit } } }

Este bloque se utiliza para interactuar con el usuario, y que nos dé feedback de si quiere continuar o no con la instalación. Se utiliza el bucle while para evitar que se presione (ENTER) o entradas inválidas a 'n', aunque para este caso he preferido que considere todo un a menos que se confirme lo contrario.

Install WinGet Packages

$WinGet = @( "Microsoft.PowerToys", "PuTTY.PuTTY", "RARLab.WinRAR", "SlackTechnologies.Slack", "Zoom.Zoom", "JetBrains.Toolbox", # {...muchos más paquetes...} ) foreach ($item in $WinGet) { Install-WinGetApp -PackageID "$item" }

Este patrón de bloque, se repite varias veces en el código para hacer la instalación de las diferentes aplicaciones, tanto en WinGet, como en Chocolately o Scoop.

Seleccionar qué navegadores web quieres instalar

$applicationsOpt = [PsCustomObject]@{ Name = "Google Chrome"; Id = "Google.Chrome" }, [PsCustomObject]@{ Name = "Sidekick"; Id = "PushPlayLabs.Sidekick" }, [PsCustomObject]@{ Name = "Mozilla.Firefox"; Id = "Mozilla.Firefox" }, [PsCustomObject]@{ Name = "Opera"; Id = "Opera.Opera" } $selectedApplicationsOpt = $applicationsOpt | Select-Object -Property Name, Id | Out-GridView -Title "Selecciona con (Shift + clic) o (Ctrl + clic) una o más navegares web a instalar y pulsa (ENTER) para ejecutar:" -PassThru | Select-Object -ExpandProperty Id Write-Host "Navegadores web seleccionados para instalar: $selectedApplicationsOpt" $WinGet = @( $selectedApplicationsOpt ) foreach ($item in $WinGet) { Install-WinGetApp -PackageID "$item" }

Siguiendo el bloque anterior, así es como haríamos para crear un menú interactivo en el que el usuario puede elegir qué aplicaciones opcionales quiere instalar, en este caso, el navegador web que quiere.

Sidekick-Demo

Entonces, con estos bloques de código tenemos la siguiente información:

Funciones

Las funciones se construyen de la siguiente manera:

function Greetings { param ( [string]$name ) # Cuerpo de la función }

y se llaman así:

Greetings -name "Noelia"

Condicional If

Las condiciones if se construyen de esta manera:

if (condición) { # Acción a realizar si la condición es verdadera } elseif (condición) { # Acción a realizar si la primera condición es falsa y esta es verdadera } else { # Acción a realizar si ninguna de las condiciones anteriores es verdadera }

Ejemplos:

Ejemplo 1: uso de 'and'

$num = 10 if ($num -gt 5 -and $num -lt 20) { Write-Host "El número está entre 5 y 20." }

Ejemplo 2: uso de 'or'

$name = "Juan" if ($name -eq "Juan" -or $name -eq "Pedro") { Write-Host "El nombre es Juan o Pedro." }

Ejemplo 3: anidación de condiciones

$age = 30 if ($age -gt 18) { if ($age -gt 25) { Write-Host "La edad es mayor que 25 años." } else { Write-Host "La edad es mayor que 18 años pero menor o igual que 25 años." } } else { Write-Host "La edad es menor o igual que 18 años." }

Impresión de mensajes por pantalla

Comando en power shellDescripción
Write-HostImprime un mensaje en la consola de PowerShell y es el comando más común para imprimir texto en PowerShell.
Write-OutputImprime un objeto o valor en la consola de PowerShell.
Write-VerboseImprime un mensaje sólo si el modo verboso está activado.
Write-DebugImprime un mensaje sólo si el modo de depuración está activado.
Write-WarningImprime un mensaje de advertencia en la consola de PowerShell.
Write-ErrorImprime un mensaje de error en la consola de PowerShell.

Ejemplo:

Write-Output "Hola mundo" Write-Host "Bienvenido al script" Write-Error "Bienvenido al script" Write-Verbose -Message "Package $Package already installed! Skipping..."

Bucles while y for

Un bucle while se crea en PowerShell con la siguiente sintaxis:

while (condition) { # bloque de código a ejecutar mientras se cumpla la condición } # Ejemplo - Imprimir los números del 1 al 10 $counter = 1 while ($counter -le 10) { Write-Output $counter $counter++ }

Un bucle for se crea en PowerShell con la siguiente sintaxis:

for ($variable in $colleccion) { # bloque de código a ejecutar en cada iteración } # Ejemplo - Imprimir los elementos de una lista de nombres $names = "John", "Jane", "Jim" for ($name in $names) { Write-Output $name }

Capturar errores con Try/Catch

El bloque try es donde se ejecutan los comandos que pueden fallar, y el bloque catch es donde se especifican las acciones a realizar en caso de un error.

Ejemplo:

try { # Código que puede fallar Write-Output "Realizando una operación peligrosa..." Get-ChildItem C:\NoExiste } catch { # Acción a realizar en caso de un error Write-Output "Ha ocurrido un error: $($_.Exception.Message)" }

Comandos útiles

  • Start-Sleep: detiene la ejecución del script por un número de segundos especificado.
  Start-Sleep -Seconds 5
  • Restart-Computer: reinicia el equipo.
Restart-Computer -Force
  • Get-Command: devuelve un objeto que representa un comando específico, en este caso se busca una aplicación con el nombre especificado.
Get-Command -Name "nombre_aplicacion" -CommandType Application -ErrorAction SilentlyContinue
  • '`n': representa un salto de línea, equivalente a '\n' en otros lenguajes de programación.
Write-Output "`nInstalación completada!"
  • Out-GridView: El usuario puede seleccionar uno o más objetos personalizados a través de esta ventana y pulsar ( ENTER) para ejecutar el script.
Out-GridView -Title "Selecciona con (Shift + clic) o (Ctrl + clic) una o más navegares web a instalar y pulsa (ENTER)
para ejecutar:" -PassThru
  • Select-Object: Se utiliza para seleccionar un subconjunto de propiedades de un objeto o una serie de objetos. Puede usarse para elegir las propiedades que deseas incluir en la salida, renombrar las propiedades existentes, calcular valores de nuevas propiedades basadas en propiedades existentes y reordenar las propiedades en la salida. Es una herramienta muy útil para manipular y personalizar la salida en PowerShell.
$applicationsOpt =
[PsCustomObject]@{ Name = "Google Chrome"; Id = "Google.Chrome" }
$selectedApplicationsOpt = $applicationsOpt | Select-Object -Property Name, Id
  • set-alias: Creación de alias en la consola
set-alias -name gco -value 'git checkout' -Scope Global