Cómo poner barras de progreso en tus scripts de PowerShell

Cada vez son más los administradores de sistemas que utilizan PowerShell, y no es para menos! PowerShell nos facilita enormemente nuestro día a día, sobre todo en tareas de gestión y automatización de procesos.

Aunque estemos trabajando con líneas de comando, es posible lograr una "interfaz" bastante amigable, pero lo importante es que sea verdaderamente práctica. Si hemos desarrollado un script con procesos en segundo plano, tal vez será recomendable añadir una barra de progresos, sobre todo para no desesperar al usuario y hacerle saber que todo está funcionando correctamente.

Para crear una barra de progresos en PowerShell, vamos a utilizar el cmdlet Write-Progress, que aunque cuenta con varios parámetros, sólo Activity es requerido. Veamos como funciona con un sencillo script, empezamos desde lo más básico e iremos añadiendo nuevos parámetros para conocerlos al detalle:

[ps]$computerList = 'equipo01', 'equipo02', 'equipo03', 'equipo04', 'equipo05', 'equipo06', 'equipo07', 'equipo08', 'equipo09', 'equipo10'
foreach ($computer in $computerList) {
Write-Progress -Activity 'Procesando equipos'
Start-Sleep -Milliseconds 500
}[/ps]

 

Ahora vamos a añadirle el parámetro CurrentOperation, para que nos muestre en qué estado se encuentra.

[ps]$computerList = 'equipo01', 'equipo02', 'equipo03', 'equipo04', 'equipo05', 'equipo06', 'equipo07', 'equipo08', 'equipo09', 'equipo10'
foreach ($computer in $computerList) {
Write-Progress -Activity 'Procesando equipos' -CurrentOperation $computer
Start-Sleep -Milliseconds 500
}[/ps]

 

Sí, ya lo sé! Hasta ahora no hemos visto una barra de progreso como tal, pero ya ha llegado la hora! Para poder mostrar la barra de progreso, necesitamos llamar al parámetro PercentComplete. Para poder trabajar con este parámetro, necesitamos un contador que posicione el progreso de la barra. En este caso, como tenemos 10 equipos, cada equipo irá contando 10 hasta llegar al 100%.

[ps]$computerList = 'equipo01', 'equipo02', 'equipo03', 'equipo04', 'equipo05', 'equipo06', 'equipo07', 'equipo08', 'equipo09', 'equipo10'
$counter = 0
foreach ($computer in $computerList) {
$counter++
Write-Progress -Activity 'Procesando equipos' -CurrentOperation $computer -PercentComplete (($counter / $computerList.count) * 100)
Start-Sleep -Milliseconds 500
}[/ps]

Esto ya ha cogido la forma que buscábamos! :-) ¿Quieres más? Venga, veamos ahora cómo funcionaría el script con múltiples barras de progreso.

Múltiples barras de progreso

En este ejemplo estoy listando ficticiamente 10 equipos, y en cada uno estoy recibiendo todos los servicios, haciendo bucle en cada uno para obtener todas las dependencias asociadas. Para cada bucle obtenemos un contador para que pueda mostrar la barra de progreso. Cuando trabajamos con varias barras de progreso, debemos utilizar los parámetros ID y ParentID para relacionarlas. El siguiente script lo podéis descargar desde el Centro de scripts de Microsoft TechNet Gallery.

[ps]$computerList = 'equipo01', 'equipo02', 'equipo03', 'equipo04', 'equipo05', 'equipo06', 'equipo07', 'equipo08', 'equipo09', 'equipo10'
$c1 = 0
foreach ($computer in $computerList) {
$c1++
Write-Progress -Id 0 -Activity 'Comprobando servidores' -Status "Procesando $($c1) de $($computerList.count)" -CurrentOperation $computer -PercentComplete (($c1/$computerList.Count) * 100)
$services = Get-Service
$c2 = 0
foreach ($service in $services) {
$c2++
Write-Progress -Id 1 -ParentId 0 -Activity 'Obteniendo servicios' -Status "Procesando $($c2) de $($services.count)" -CurrentOperation $service.DisplayName -PercentComplete (($c2/$services.count) * 100)
$c3 = 0
if ($service.ServicesDependedOn) {
  foreach ($dependency in $service.ServicesDependedOn) {
  $c3++
  Write-Progress -Id 2 -ParentId 1 -Activity 'Obteniendo dependencias' -Status "Procesando $($c3) de $($service.ServicesDependedOn.Count)" -CurrentOperation $dependency.Name -PercentComplete (($c3/$service.ServicesDependedOn.count) * 100)
  Start-Sleep -Milliseconds 50
  }
}
else {
Write-Progress -Id 2 -ParentId 1 -Activity 'Obteniendo dependencias' -PercentComplete 100
}
Start-Sleep -Milliseconds 50
}
Start-Sleep -Milliseconds 50
}[/ps]

 

Algo muy curioso que podemos encontrar en Write-Progess es que siempre trata de optimizar el espacio utilizado en la consola. Digamos que tiene un comportamiento "responsive", de modo que nos mostrará el porcentaje de manera numérica cuando la ventana sea pequeña, y la barra de progreso cuando la ventaja sea grande. Podemos realizar la prueba maximizando la ventana.

Como podéis ver, es muy sencillo añadir barras de progreso a los scripts de PowerShell, y nuestros usuarios lo agradecerán! 🙂

 

Sobre el autor:

Daniel Alonso, Microsoft MVP de Windows and Devices for IT

Cloud Solutions Principal Advisor @ENCAMINA