mayho33
Goto Top

Start-Process gibt tlw. keinen ReturnCode aus (PowerShell)

Hallo @ All!

Irgendwie stehe ich wieder mal am Schlauch und hoffe wieder auf tatkräftige Starthilfe!

Hier mein Problem:

Ich rufe eine Exe auf via: $RC = (Start-Process -FilePath <Irgend eine exe> /s -PassTru)
-Wait gebe ich absichtlich nicht an ich will nämlich, dass in der PS-Console sowas wie ein Fortschrittsbalken läuft. das mache ich so:

do {
write-host "*" -NoNewLine
if ($RC.ExitCode -gt -1) { Break}
Start-Sleep 1
} until ($RC.ExitCode -gt -1)

write-host ("ExitCode: + $RC.ExitCode)


Jetzt kommt es vor, dass entweder die Schleife nicht beendet wird obwohl der ExitCode sicher 0 oder höher ist, oder der ExitCode ist $null.
mit -Wait bekomme ich natürlich immer eine ExitCode, da habe ich aber auch keine Fortschrittsbalken. Den will ich aber unbedingt haben, weil einige EXEn und MSIs ziemlich groß sind und entsprechend lange brauchen.


Hat jemand ne Idee wie ich da eine saubere und vor allem sichere Lösung zustande bekomme??

Danke!

Mayho

Content-ID: 227812

Url: https://administrator.de/contentid/227812

Ausgedruckt am: 27.11.2024 um 16:11 Uhr

colinardo
colinardo 27.01.2014 aktualisiert um 01:01:50 Uhr
Goto Top
Hallo Mayho,
Schau dir mal dieses Mulithreading-Beispiel an:
Powershell GUI bleibt während einer While schleife hängen...
Würde den Prozess in einen parallelen Thread verlagern worin du dann mit -wait auf den Prozess wartest und dann den Exit-Code an den Hauptthread übergibst. Gerade bei MSI-Dateien ist es so das die Shell auf das Ende von msiexec warten sollte, denn sonst kommt es zu dem Phänomen das ein falscher Exit-Code ausgegeben wird (das liegt daran das msiexec ursprünglich nicht als Konsolenanwendung ausgelegt worden ist)

Was auch eine Möglichkeit wäre ist das CMDlet Start-Job mit dem sich so was realisieren ließe. Melde mich dazu nochmal...

Bis dahin ...
Grüße Uwe
colinardo
Lösung colinardo 27.01.2014, aktualisiert am 10.02.2014 um 17:07:14 Uhr
Goto Top
Noch ein Beispiel wie du es machen kannst:
# Hashtable beinhaltet später die Informationen aus dem parallelen Thread
$rc = @{}

# Neuen Thread erstellen
$myjob = [Powershell]::Create().AddScript({
    param($result)
    
    # hier dein Aufruf deiner MSI-Datei 
    $r = start-process "msiexec /i install.msi /qn" -wait -PassThru  

    $result.ExitCode = $r.ExitCode
}).AddArgument($rc)

# Thread starten
$myjob.BeginInvoke()| out-null

# Warte auf das Ende des Threads
while($myjob.InvocationStateInfo.State -eq "Running"){  
    write-host "*" -NoNewLine  
    sleep(1)
}
# Gebe ExitCode aus
echo "`r`nExit-Code: $($rc.ExitCode)"  
Grüße Uwe
mayho33
mayho33 29.01.2014, aktualisiert am 10.02.2014 um 17:07:03 Uhr
Goto Top
Hi Uwe!

Danke für die beiden Beispiele! Werde das mal in ner ruhigen Minute durchgehen. Multithreading habe ich noch nicht bedacht. Finde das ist eine tolle Idee.

Danke!

Mayho

EDIT

Hi Uwe!

nun hatte ich endlich Zeit das in meinen Code einzubauen.

Das zweite Beispiel von dir hat wunderbar geklappt ohne groß was anpassen zu müssen. Das Resultat ist wie gewünscht eine Progressanzeige in der Console. Auch die Returncodes kommen wie sie sollen.

Perfekt!! Vielen Dank!

Was habe ich daraus gelernt? Bei Problemen Uwe fragen :P

lg

Mayho!
MPascalau
MPascalau 15.08.2015 um 18:46:06 Uhr
Goto Top
Ich habe vor lange Zeit gelesen, dass PowerShell mit ExitCode Eigenschaft von Process ein Problem hat.
Die Erklärung war viel zu Kompliziert, und ich habe vergessen.

Ich habe das Problem so korrigiert:
function Get-ProcessExitCode {
[CmdletBinding()]
param(
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[System.Diagnostics.Process]$Process)
Begin {
$private:type = [System.Diagnostics.Process]
$private:prop = $private:type.GetProperty("ExitCode")
}
Process {
return $private:prop.GetValue($Process)
}
}

$RC.WaitForExit() # Wait for process to finish!
$exitcode = Get-ProcessExitCode $RC # Get the ExitCode