Question [Fonction]Invoke-ConsoleProgram (gestion des flux)

Plus d'informations
il y a 11 ans 6 mois #12899 par Laurent Dardenne
Voici une fonction exécutant une ligne de commande, un programme console, utilisant le flux d'erreur système (stderr) pour émettre soit des erreurs soit des warning dans le pipeline Powershell.

Si le programme console émet des warnings sur le flux d'erreur celui-ci polluera la collection d'erreur, de plus ces avertissements ou considérés comme tels, ne seront pas émit sur le bon flux Powershell.

On aimerait donc quelques fois ne pas impacter la liste d'erreur $Error et dissocier d'une même source les erreurs des warning, voir du simple texte ( mode verbose).

Pour ne pas impacter la liste d'erreur $Error on utilisera un job, qui crée un état de session différent, donc sa propre collection d'erreur.
Il restera à parser le résultat, comme par exemple :
[code:1]
Receive-Job $Job | Foreach {
$Line=$_
switch -regex ($Line) {
' : warning (?<Code>.*[^:]) : (?<Message>.*)' {Write-Warning (\"{0} : {1}\" -f $Matches.Code,$Matches.Message)}
' : error (?<Code>.*[^:]) : (?<Message>.*)' {Write-Error (\"{0} : {1}\" -f $Matches.Code,$Matches.Message)}
'^TlbImp : (?<Message>(?!warning|error).*)' {Write-Verbose (\"{0}\" -f $Matches.Message)}
} #switch
}
[/code:1]
Ce code interprète le résultat d'exécution et associe les messages d'informations à un flux PS dédié.
[code:1]
Function Invoke-ConsoleProgram{
[cmdletBinding()]
Param (
[string] $CommandLine,
[ScriptBlock] $Parseur,
[string] $Location
)
#Permet d'exécuter un process utilisant le handle stderr pour afficher des warning ou des erreurs
#Ainsi le flux d'erreur ($Error) de l'appelant n'est pas 'pollué' par cette gestion des erreurs spécifique au process

#Cette fonction reçoit un seul paramètre contenant une ligne de commande
#Celle-ci doit débuter par l'opérateur & et se terminer par une instruction de redirection du flux d'erreur standard vers le pipeline powershell :
#'&NomDeProgrammeComplet liste_de_paramètres 2>&1\"
# Exemple :
# $Cmd ='&\"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\TlbImp.exe\" \"C:\Windows\system32\activeds.tlb\" /out:\"C:\Temp\Interop.activeds.dll\" /namespace:Interop.activeds /asmversion:\"1.0.0\" 2>&1'

try {
$Job=Start-Job -Argumentlist $Location,$CommandLine {
Param ($Location, $CommandLine)
#Si la commande crée un fichier dans le répertoire par défaut de l'appelant
#on doit modifier le répertoire courant du Runspace
Set-Location $Location

$ErrorActionPreference=\"Continue\"
$WarningActionPreference=\"Continue\"
Invoke-Expression $CommandLine
}| Wait-Job

#A partir d'une string contenant du code, on crée un ScriptBlock afin d'utiliser le scope de ce module.
#Sinon, dans le cas où on passe un SB créé dans un autre module, on utiliserait le scope du module appelant !
# La variable $Job reste donc accessible
$SBParseur=[System.Management.Automation.ScriptBlock]::Create($Parseur)
#Parse le résultat afin d'écrire dans les flux correspondants
Receive-Job $Job | Foreach $SBParseur
} finally {
if ($job -ne $null)
{Remove-Job $Job.id}
}
} #Invoke-ConsoleProgram
[/code:1]
C'est une mécanique un peu lourde, mais pour l'instant je n'ai pas trouvé d'autre moyen en natif.

L'appelant pourra très bien utiliser les variables communes tout en jouant sur les variables de préférence :
[code:1]
#N'affiche pas les warning sur la console
$WarningPreference='SilentlyContinue'
#récupère les erreurs et les warning dans deux collection distinctes
ConvertTo-InteropAssembly -TlbPath 'C:\Windows\system32\activeds.tlb' -ErrorVariable tlbError -WarningVariable tlbWarning
[/code:1]
Ainsi la collection $Error contiendra de véritable erreur et pas du 'bruit'.<br><br>Message édité par: Laurent Dardenne, à: 12/10/12 11:58

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 11 ans 6 mois #12902 par Laurent Dardenne
Une correction :
Ajout du paramètre $Location
Si la commande exécutée crée un fichier en référençant le répertoire par défaut de l'appelant, alors on doit modifier le répertoire courant du Runspace, sinon celui-ci pointera sur le répertoire utilisateur.

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.067 secondes
Propulsé par Kunena