Eviter les conflits d’installation concurrente sous MSIEXEC

I. Présentation

Voici un petit retour d’expérience susceptible de vous intéresser dans le cadre de vos installations automatisées sous Windows. En effet, lorsque vous réalisez des installations dans le cadre d’un séquenceur, tel que MDT ou un simple script, il est assez facile de maîtriser les instances successives du moteur d’installation (aka MSIEXEC) au travers une instruction d’attente de processus.

 

II. Explications

Autrement dit, pour chaîner un ensemble d’installations au travers de script, vous pouvez recourir à des commandes du genre (Exemples non exhaustifs) :

En batch

start /wait %windir%\system32\msiexec.exe /i ~dp0MonAppli_1\Setup1.msi /qb-
start /wait %windir%\system32\msiexec.exe /i ~dp0MonAppli_2\Setup2.msi /qb-

En Powershell

Start-Process -FilePath "$env:windir\system32\msiexec.exe" -ArgumentList  "/i","$pwd\MonAppli_1\Setup1.msi","/qb-" -Wait
Start-Process -FilePath "$env:windir\system32\msiexec.exe" -ArgumentList  "/i","$pwd\MonAppli_2\Setup2.msi","/qb-" -Wait

La directive « Wait » permet d’attendre la fin du processus d’installation avant de passer à la suite.

Imaginons maintenant, que ces différentes installations (ou désinstallations) ne soient pas déclenchées par le même ordonnanceur, comme par exemple, l’exécution en parallèle de 2 scripts différents, cela engendre un conflit et donc une erreur d’exécution.

msiexec_1

Erreur « 1618 – ERROR_INSTALL_ALREADY_RUNNING »

Ce message correspond au code d’erreur « 1618 – ERROR_INSTALL_ALREADY_RUNNING » du moteur d’installation MSIEXEC (cf Codes erreurs MSI )

En cherchant un peu sur le net, vous trouverez des exemples permettant de tester, et le cas échéant d’attente un processus, comme par exemple en Powershell :

$process = "notepad"
$ErrorActionPreference = 'SilentlyContinue'
While ((Get-Process $process) -ne $null)
{
  Start-Sleep -Seconds 1
  write-host -fore red "Attente de fermeture du processus $process ..."
}
write-host -fore green "Aucun processus $process en cours..."

Cet exemple attend la fermeture du processus « notepad » avant de poursuivre son exécution. Toutefois, si vous transposez ce script au moteur d’installation $process = « msiexec », vous constaterez que celui-ci sera inopérant.

 

A. Pourquoi cette technique ne fonctionne pas avec MSIEXEC ?

Ceci est lié au fait que lorsqu’une installation MSI est en cours, il y a plusieurs processus MSIEXEC qui sont instanciés ET qu’une fois l’installation terminée, un dernier processus reste actif… (Et en plus il dure « un certain temps » comme disait Fernand Raynaud 😀 )

Pour vous en assurer, exécutez un package MSI quelconque sans poursuivre l’installation, juste histoire d’ouvrir l’interface graphique. Dans une session Powershell, tapez la commande suivante :

gps msiexec

Vous devriez voir apparaître un minimum de 2 processus. Fermez l’interface d’installation du package MSI puis exécutez de nouveau la commande précédente.

Vous pouvez constater qu’un processus « msiexec » est encore en cours d’exécution et ceci pendant un bonne dizaine de minutes.

 

B. Contournement de cette particularité

Il est évident que la terminaison forcée d’un processus MSIEXEC n’est pas une bonne solution du fait que cela risque d’altérer une installation en cours.

Je vous propose donc le squelette de script Powershell suivant :

$Engine = "$ENV:windir\system32\msiexec.exe"
$Package = "c:\Sources\Appli-Setup.msi"
$arglist = @(
     " /i"	
     " $Package"
     " /qn"
     " /norestart"
)

# --- Vérifie qu'il n'y a pas d'installation MSI en cours 
while ( (Get-Process | Where-Object { $_.ProcessName -eq "msiexec" }).count -gt 2)
{ 
  start-sleep -second 3
  Write-Host -ForegroundColor Yellow "Une autre installation est en cours ... Veuillez patienter."
}

# --- Installation du package MSI
Write-Host -ForegroundColor Green "La voie est libre, on démarre notre installation."
Start-Process -FilePath $Engine -ArgumentList $arglist -Wait

Enregistrez ce script sous « Wait-MSI.ps1 »

Relancez une installation de MSI comme précédemment puis exécutez le script en parallèle dans une session Powershell.Attendez quelques secondes, afin de constater l’affichage des messages « … Veuillez patienter. » puis terminez le programme d’installation MSI via l’interface graphique. Ces actions devraint vous afficher le résultat suivant :

msiexec_2

Exemple de résultat à la fermeture du programme d’installation

Voilà, j’espère que cette petite astuce vous rendra quelques services dans vos taches de déploiement applicatifs sous Windows.

 

Bien à vous