2016-09-08 3 views
0

Ich kann ein PowerShell-Skript nicht stoppen, wenn die Batch-Skripts, die von diesen PowerShell-Skripten aufgerufen werden, einen Fehler ausgeben.Ausführung des PowerShell-Skripts stoppen und zur ursprünglichen Stapeldatei zurückkehren

bittet 1:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%\CallInstall.ps1'"; 

CallInstall.ps1 Anrufe paar Batch-Dateien und vbs-Dateien im Fall eines Ausfalls einer Voraussetzung nennt das bat2 eine vbs basierten Message-Box einen Fehler anzuzeigen. Im Idealfall sollte zu diesem Zeitpunkt die Ausführung stoppen und der Bat1 sollte den verbleibenden Prozess starten, aber in meinem Fall CallInstall.ps1 führt immer noch alle Batch-und VBS-Skripte vor dem Zurückgehen zu bat1.

CallInstall.ps1:

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null 
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null 

Set-Location $PSScriptRoot 

$ScriptsHome = Get-Item '.\ScriptInstall\*' 

#Define Form 
$Form = New-Object System.Windows.Forms.Form 
$Form.width = 1000 
$Form.height = 200 
$Form.Text = "** Installation in Progress**" 
$Form.Font = New-Object System.Drawing.Font("Times New Roman" ,12, [System.Drawing.FontStyle]::Regular) 
$Form.MinimizeBox = $False 
$Form.MaximizeBox = $False 
$Form.WindowState = "Normal" 
$Form.StartPosition = "CenterScreen" 
$Form.Opacity = .8 
$Form.BackColor = "Gray" 

# Init ProgressBar 
$ProgressBar = New-Object System.Windows.Forms.ProgressBar 
$ProgressBar.Maximum = $ScriptsHome.Count 
$ProgressBar.Minimum = 0 
$ProgressBar.Location = new-object System.Drawing.Size(10,70) 
$ProgressBar.size = new-object System.Drawing.Size(967,10) 
$Form.Controls.Add($ProgressBar) 
#$Form.Controls.Add($MessagesLabel) 

#Running Script Name 
#$Label = New-Object System.Windows.Forms.Label 
#$Label.AutoSize = $true 
#$Label.Location = New-Object System.Drawing.Point(10,50) 
#$Form.Controls.Add($Label) 

#Define Array messages 
#Array 
$Messages = @("Message 1", 
       "Message 2", 
       "Message 3", 
       "Message 4", 
       "Message 5", 
      ) 
$MessagesLabel = New-Object System.Windows.Forms.Label 
$MessagesLabel.AutoSize = $true 
$MessagesLabel.Location = New-Object System.Drawing.Point(10,50) 
$Form.Controls.Add($MessagesLabel) 

# Add_Shown action  
$ShownFormAction = { 
    $Form.Activate() 

    foreach ($script in $ScriptsHome) { 
     $ProgressBar.Increment(1) 
     $MessagesLabel.Text = $Messages[$ProgressBar.Value - 1] 
     Start-Process $script.FullName -Wait -WindowStyle Hidden 
    } 
    $Form.Dispose() 
} 
$Form.Add_Shown($ShownFormAction) 

# Show Form 
$Form.ShowDialog() 

#Create Logs 
Invoke-Expression -Command .\LogScript.ps1 

Im Inneren des ScriptInstall Ordner gibt es 10 Batch und vbs-Skripten auf einen der Batch-Skript:

:error 
cscript %base_dir%\fail.vbs > %Log% 
:match 
findstr /I /c:"xxxx" c:\match.txt 
if %errorlevel% == 0 (
    goto nextStep 
) else (
    goto ErrorCheck 
) 

und in fail.vbs:

Dim vbCrLf : vbCrLf = Chr(13) & Chr(10) 
Set WshShell = WScript.CreateObject("WScript.Shell") 
MsgBox "Installation Fail !!!" & vbCrLf & "Message1" & vbCrLf & "Click OK to Exit" , 16, "Fail" 

Idealer nach dem Drücken ok auf diesem fail.vbs Die Box CallInstall.ps1 sollte nicht mit dem Rest der Skripte im ScriptInstall-Ordner fortfahren, aber ansonsten. Es wird mit den verbleibenden Skripten im ScriptInstall-Ordner fortgesetzt und die Ausführung anschließend an bat1 zurückgegeben.

+0

Wenn möglich, wird es viel einfacher, die Logik und Stop/Continue-Schritte beizubehalten, wenn Sie so viel von der Logik in einen Skript-Typ bewegen, anstatt PowerShell von bat aufrufen und andere Batch-Dateien aufrufen VBScript. In Ihrer Instanz 'as-is', ohne OK/cancel, müssen Sie einen Nicht-Null-Fehlercode aus Ihrem VBScript zurücksenden, wie folgt: WScript.Quit 1 – TechSpud

Antwort

1

Sie könnten mit exitcodes arbeiten und Ihre Skripte wie folgt ändern:

Die Powershell-Skript:

foreach ($script in $ScriptsHome) { 
    $ProgressBar.Increment(1) 
    $MessagesLabel.Text = $Messages[$ProgressBar.Value - 1] 
    $process = Start-Process $script.FullName -Wait -WindowStyle Hidden -passthru 
    if($process.ExitCode -ne 0){break} 
} 

Die Batch-Skript:

:error 
cscript %base_dir%\fail.vbs > %Log% 
Exit /b 1 
+0

Ich habe diese Änderung auch mit 'echo yes> c versucht: \ batchpass.txt' in der ersten Batch-Datei, aber die Powershell wird nach dem Aufruf des ersten Skripts beendet. – n00b

+0

Ich bin mir nicht sicher, was deine Frage ist. Aber ich gehe davon aus, dass die Powershell-Anwendung beendet wird, weil die Batchdatei nicht mit 0 beendet wurde. Können Sie den vollständigen Code dieser Batchdatei posten? Was passiert, wenn Sie nur Ihre Batchdatei ausführen? Geht es darum, was es tun soll? – A189198

+0

Die Batch-Datei hat 'net stop'- Acronis VSS-Provider" net stop "COM + Systemanwendung" ' – n00b

0

Der allgemeine Ansatz ist von der Ausfahrt Batch-Skripte mit einem Exit-Code ungleich Null im Falle eines Fehlers und Überprüfen des Exit-Status im PowerShell-Code, wie @A189198 bereits in seiner Antwort gezeigt.

Ich würde, fallen jedoch die VBScript vollständig (Sie Meldungsfelder von Powershell angezeigt werden können), und die Erfassung ein Process Objekt ist auch nicht erforderlich, da automatisch Powershell, die Informationen über die automatic variable$LastExitCode zur Verfügung stellt.

Ändern Sie den Fehler in Ihrem Batch-Code, so etwas wie diese Handhabung:

if %errorlevel% neq 0 exit /b 1 

und ändern Sie diese foreach Schleife:

foreach ($script in $ScriptsHome) { 
    $ProgressBar.Increment(1) 
    $MessagesLabel.Text = $Messages[$ProgressBar.Value - 1] 
    Start-Process $script.FullName -Wait -WindowStyle Hidden 
} 
$Form.Dispose() 

dazu:

foreach ($script in $ScriptsHome) { 
    $ProgressBar.Increment(1) 
    $MessagesLabel.Text = $Messages[$ProgressBar.Value - 1] 
    Start-Process $script.FullName -Wait -WindowStyle Hidden 
    if ($LastExitCode -ne 0) { [Windows.Forms.MessageBox]::Show("Installation Fail!`nMessage1`nClick OK to Exit", 'Fail', 0, 'Error') break } 
} 
$Form.Dispose()
+0

ich entschuldige mich für die verzögerte Antwort. Ich habe diese Änderung versucht, aber nur das erste Skript wird ausgeführt und dann wird die Powershell beendet, nachdem das Meldungsfeld aufgerufen wurde. Das erste Batch-Skript enthält 'echo ja> c: \ batchpass.txt' Ich verstehe nicht, was ich nicht richtig mache. – n00b

+0

Anscheinend gibt Ihr erstes Stapelscript bereits einen Beendigungscode ungleich Null zurück, sodass das PowerShell-Skript wie von Ihnen angefordert beendet wird. Wenn das Stapelscript nur die Anweisung 'echo' enthält, kann dies durch einen Fehler beim Schreiben in die Ausgabedatei verursacht werden. Andernfalls müssen Sie den Code Ihrer Batch-Datei anzeigen. –

+0

Ja, Sie sind absolut richtig. In meiner ersten Batch-Datei benutze ich den Befehl net stop, um verschiedene Dienste zu stoppen. Einige dieser Dienste sind generische Windows-Dienste, die ich zu stoppen versuche, aber manchmal kommt es vor, dass ein Dienst, der bereits gestoppt ist, einen Fehler bei der Ausführung des Skripts verursacht. Jede Methode, um damit umzugehen. – n00b

0

Vielen Dank für jeden eine, die mir den Weg zeigt, es zu tun. Ich habe die Lösung gefunden. Ich habe die foreach-Schleife in dem Powershell-Skript geändert von

foreach ($script in $ScriptsHome) { 
    $ProgressBar.Increment(1) 
    $MessagesLabel.Text = $Messages[$ProgressBar.Value - 1] 
    Start-Process $script.FullName -Wait -WindowStyle Hidden 
} 
$Form.Dispose() 

zu

foreach ($script in $ScriptsHome) { 
     $ProgressBar.Increment(1) 
     $MessagesLabel.Text = $Messages[$ProgressBar.Value - 1] 
     #$Label.Text  = "$($script.Name)" 
     Start-Process $script.FullName -Wait -WindowStyle Hidden 

     if (Select-String -Path C:\exitloop.txt "fail") 
     { 
     break 
     } else {continue 
     } 
     } 
    $Form.Dispose() 

und im ScriptInstall Ordner, in dem es 10 Chargen- und vbs-Skripten in den Batch-Skripten ich den Code geändert habe .

:error 
cscript %base_dir%\fail.vbs > %Log% 
echo fail > c:\exitloop.txt 
exit 
:match 
findstr /I /c:"xxxx" c:\match.txt 
if %errorlevel% == 0 (
    goto nextStep 
) else (
    goto ErrorCheck 
) 

so, wann immer es eine Bedingung, Fehler in der Batch-Datei ist die Batch-Datei eine TXT-Datei mit Text generieren „nicht bestanden“ dies geschieht vor Beendigung der jeweiligen Batchdatei. Unmittelbar danach kehrt die Steuerung zum Powershell-Skript zurück, das prüft, ob "fail" in c: \ exitloop.txt vorhanden ist. Wenn ja, wird die Ausführung des Powershell-Skripts selbst gestoppt, sonst wird es weiterhin die Batch- und vbs-Dateien aufrufen. Danke

Verwandte Themen