停止执行PowerShell脚本并返回到原始批处理文件

时间:2016-09-08 10:07:59

标签: powershell batch-file vbscript

如果此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.vbsCallInstall.ps1上按下确定后,不应继续使用ScriptInstall文件夹中的其余脚本,否则不会这样做。它继续使用ScriptInstall文件夹中的剩余脚本,然后将执行返回给bat1。

4 个答案:

答案 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