如果此PowerShell脚本调用的批处理脚本引发错误,则无法停止PowerShell脚本。
bat 1 :
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%\CallInstall.ps1'";
CallInstall.ps1
调用几个批处理文件和vbs文件,如果先决条件失败,bat2会调用基于vbs的消息框来显示错误。理想情况下,执行应该停止,bat1应该启动剩余的进程,但在我的情况下,CallInstall.ps1
仍然会执行所有批处理和vbs脚本,然后再返回到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
在ScriptInstall文件夹中,其中一个批处理脚本上有10个批处理和vbs脚本:
:error
cscript %base_dir%\fail.vbs > %Log%
:match
findstr /I /c:"xxxx" c:\match.txt
if %errorlevel% == 0 (
goto nextStep
) else (
goto ErrorCheck
)
和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"
理想情况下,在fail.vbs
框CallInstall.ps1
上按下确定后,不应继续使用ScriptInstall文件夹中的其余脚本,否则不会这样做。它继续使用ScriptInstall文件夹中的剩余脚本,然后将执行返回给bat1。
答案 0 :(得分:1)
您可以使用exitcodes并更改脚本,如下所示:
PowerShell脚本:
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}
}
批处理脚本:
:error
cscript %base_dir%\fail.vbs > %Log%
Exit /b 1
答案 1 :(得分:0)
一般方法是在出现错误时退出带有非零退出代码的批处理脚本,并检查PowerShell代码中的退出状态,因为@A189198已在答案中显示。
但是,我会完全删除VBScript(您也可以显示来自PowerShell的消息框),并且不需要捕获Process
对象,因为PowerShell会自动通过automatic variable提供信息$LastExitCode
。
将批处理代码中的错误处理更改为以下内容:
if %errorlevel% neq 0 exit /b 1
并更改此foreach
循环:
foreach ($script in $ScriptsHome) {
$ProgressBar.Increment(1)
$MessagesLabel.Text = $Messages[$ProgressBar.Value - 1]
Start-Process $script.FullName -Wait -WindowStyle Hidden
}
$Form.Dispose()
到此:
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()
答案 2 :(得分:0)
感谢每一位人员向我展示了如何做到这一点。我找到了解决方案。 我已经从
更改了powershell脚本中的foreach循环foreach ($script in $ScriptsHome) {
$ProgressBar.Increment(1)
$MessagesLabel.Text = $Messages[$ProgressBar.Value - 1]
Start-Process $script.FullName -Wait -WindowStyle Hidden
}
$Form.Dispose()
到
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()
并且在ScriptInstall文件夹中,批处理脚本中有10个批处理和vbs脚本,我已将代码更改为。
: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
)
因此,只要批处理文件中出现条件故障,批处理文件就会生成一个文本“失败”的txt文件,这在该特定批处理文件终止之前就会发生。在此之后,控件将立即返回到powershell脚本,该脚本将检查c:\ exitloop.txt中是否存在“fail”,如果是,这将停止执行powershell脚本本身,否则它将继续调用批处理和vbs文件。 感谢
答案 3 :(得分:0)
Exit
将退出Powershell。因此,如果您以交互方式运行,这是意料之外的。请改用Return
来停止执行剩余的代码行:
for ($i=0; $i -lt 5; $i++){
$input = $(Read-Host "Enter a number between 1 and 5")
if ($input -In (1..5)){
$IDTWinImageNum = $input -as [int]
Break
}elseIf($input -eq '0'){
Return
}
}
Write-Host
Write-Host "You selected $input"
write-host "Continued..."
当您输入0以外的任何数字时的结果:
Enter a number between 1 and 5: 9
Enter a number between 1 and 5: 7
Enter a number between 1 and 5: 4
You selected 4
Continued...
输入0时的结果:
Enter a number between 1 and 5: 0