AppScript-E. Attente de fin des processus

I. Présentation

Ce point est particulièrement important lors des processus d’installation, et devrait être systématiquement stipulé. Faites éventuellement appel à votre fonction de journalisation pour consigner le début et la fin du processus dans un journal.

Pour le cas particulier du processus d’installation MSIEXEC, je vous conseille la lecture de mon article “Eviter les conflits d’installation concurrente sous MSIEXEC

Wait-Process

II. Attendre la fin des processus pour un séquencement maîtrisé

1. Techniques de base

(Batch)

En batch, il suffit de préfixer l’action d’installation par la commande “start /wait” comme par exemple ::

start /wait msiexec /i MonPackage.msi /qb

(VBscript)
En vbscript, vous pouvez utiliser la méthode “Run” de l’objet “Shell”. Si la valeur booléenne “bWaitOnReturn” est vraie, le script attend la terminaison du processus avant de poursuivre.

Const bWaitOnReturn = True
Set WshShell = CreateObject("Wscript.Shell")
WshShell.Run ("msiexec /i MonPackage.msi /qb",,bWaitOnReturn)

Note : Sauf pour les cas de gestion des  , je vous déconseille le recours à la méthode “Exec” qui nécessite l’usage d’une boucle d’attente et l’évaluation de la propriété “.status” afin de contrôler la fin du processus.

 

(PShell)
En Powershell, le plus évident consiste à recourir à l’applet de commande “Start-Process -Wait” :

Start-Process -Wait -FilePath "$env:windir\system32\msiexec.exe" -ArgumentList @("/i","MonPackage.msi","/qb") 

Dans certains cas particuliers, vous pouvez avoir besoin de recourir aux taches d’arrière plan (Alias “Jobs”). Il existe de nombreux articles sur le sujet mais pour en dresser les grandes lignes, sachez que Powershell propose des applets de commande dédiées, telles que “Start-Job, Wait-Job, Receive-Job” mais sur ceratines commandes, le commutateur “-asJob“, typiquement lors des appels WMI.

Ajoutez le code suivant dans votre script, pour vous assurer que toutes les taches  d’arrière plan sont achevées avant de poursuivre.

# Exemple de requete WMI en arrière-plan
Get-WmiObject win32_product -AsJob

# Attente de terminaison
get-job | wait-job 

2. Maîtrise des sorties d’affichage

Cet aparté est issu d’un petit retour d’expérience : En effet, si vous utilisez une technique telle que “start-transcript / stop-transcript” pour consigner les retours d’exécution de vos scripts Powershell lancé par le MDT, vous constaterez que la perte d’information est très importante, voire inexistante dans certains cas.

Ceci est lié au comportement par défaut de l’applet de commande “Start-Process” et la notion de console $Host vers laquelle les flux et sorties d’affichage sont redirigés par défaut. Au besoin, reportez-vous à mon article sur le sujet http://www.it-connect.fr/powershell-pour-les-debutants-4eme-partie/

Une première solution serait d’écrire une fonction alternative à “Start-Process” comme suit :

Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
 $pinfo = New-Object System.Diagnostics.ProcessStartInfo
 $pinfo.FileName = $commandPath
 $pinfo.RedirectStandardError = $true
 $pinfo.RedirectStandardOutput = $true
 $pinfo.UseShellExecute = $false
 $pinfo.Arguments = $commandArguments
 $p = New-Object System.Diagnostics.Process
 $p.StartInfo = $pinfo
 $p.Start() | Out-Null
 $p.WaitForExit()
 [pscustomobject]@{
  commandTitle = $commandTitle
  stdout = $p.StandardOutput.ReadToEnd()
  stderr = $p.StandardError.ReadToEnd()
  ExitCode = $p.ExitCode 
 }
}

$LogFile = "C:\Scripts\install.log"
Start-Transcript -Path $LogFile -Verbose

$Cmd = "$env:windir\System32\cscript.exe"
$arglist = @(
 "//Nologo",
 "c:\Scripts\BIOS.vbs"
 )
Write-Output "Exécution de la commande :`n$Cmd $arglist"
# $Process = Start-Process -FilePath $cmd -ArgumentList $ArgList -wait -NoNewWindow -PassThru
$Result = Execute-command -commandTitle "Script" -commandPath $Cmd -commandArguments $arglist
Write-Output $Result.Stdout
Write-Output "* Code de retour : $($Result.ExitCode) **** (0 = OK, pas d'erreur)"

Stop-Transcript 

Une seconde approche, inspirée de l’exemple du site https://deploymentbunny.com/category/powershell/ , consiste à “améliorer” et affiner l’appel de la commande :

Function Invoke-Exe{
    [CmdletBinding(SupportsShouldProcess=$true)]
    param(
        [parameter(mandatory=$true,position=0)]
        [ValidateNotNullOrEmpty()]
        [string]$Executable,
        [parameter(mandatory=$false,position=1)]
        [string]$Arguments
    )
    if($Arguments -eq "")
    {
        Write-Verbose "Execution de Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru
    }else{
        Write-Verbose "Execution de Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru
    }
    Write-Verbose "Code retour : $($ReturnFromEXE.ExitCode)"
    Return $ReturnFromEXE.ExitCode
}

 

Retour au sujet principal

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. Apprenez comment les données de vos commentaires sont utilisées.