windows - 从 Powershell 调用 .exe 时如何防止出现 "Program has stopped working"对话框

标签 windows powershell windows-error-reporting

我正在编写一个 PS 脚本来生成大量 Crystal Reports (Windows 7) 的 .xml 表示。在此脚本中,我创建了一个代表所有需要解析的文件的对象,然后遍历它们,对它们逐一调用 .exe。有时,此 .exe 会崩溃。这很好,因为它非常罕见,而且无法处理的报告可以手动标记和审查。问题是我有数千个 .rpt 文件要处理,当 .exe 崩溃时,Windows 会弹出一个对话框,要求调试或继续。

enter image description here

我为解决问题所做的尝试:

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting\DebugApplications:我把我的 exe 名称放在这里并将值设置为 0(不要调试)

  • HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\DebugApplications:同上

  • 设置调用exe的循环为SilentlyContinue

  • 按如下方式关闭错误报告:控制面板 > 操作中心 > 更改操作中心设置 > 问题报告设置 > 为所有用户更改报告设置 > “从不检查解决方案”> 确定 > 确定(这只会禁用“Windows 可以在线检查...”对话框)

不过,我收到了弹出窗口。还有另一个注册表项,它完全禁用“程序已停止工作”UI,但我不想这样做,因为作为其他应用程序的开发人员,我需要知道什么时候崩溃。我只想从显示 UI 中排除此脚本或它调用的 exe。

如果我能做到这一点,那么脚本就可以在无人值守的情况下运行。

行为不当的 .exe 是来自此处的最新二进制版本:https://github.com/ajryan/RptToXml并且在报告文件中遇到空字节时似乎失败了。

这是我的代码:

[xml]$MainConfigFile = Get-Content "settings.config.xml"
[xml]$SSRSConfigFile = Get-Content "ssrs.config.xml"
[xml]$CrystalConfigFile = Get-Content "crystal.config.xml"

# create settings objects from xml objects
$MainSettings = @{
    OutputPath = $MainConfigFile.Settings.OutputPath
    SearchString = $MainConfigFile.Settings.SearchString
    ParseCrystal = $MainConfigFile.Settings.ParseCrystal
    ParseSSRS = $MainConfigFile.Settings.ParseSSRS
}

$CrystalSettings = @{
    InputFolderPath = $CrystalConfigFile.CrystalSettings.InputFolderPath
    ContinueOnError = $CrystalConfigFile.CrystalSettings.ContinueOnError
}

$RsSettings = @{
    ReportServerUri = $SSRSConfigFile.RsSettings.ReportServerUri
    RsVersion = $SSRSConfigFile.RsSettings.RsVersion
}

Clear

Write-Host "Ensure these settings are correct before you proceed:" -ForegroundColor Yellow
Write-Host ""

Write-Host "Main Settings" -ForegroundColor Green
$MainSettings
Write-Host ""

Write-Host "Crystal Settings" -ForegroundColor Green
$CrystalSettings
Write-Host ""

Write-Host "SSRS Settings" -ForegroundColor Green
$RsSettings
Write-Host ""

# user must confirm
[string]$SettingsOK=(Read-Host "[Y] to proceed, [N] to quit:")
if ($SettingsOK -ne "Y") {exit}

Write-Host ""
Write-Host "______________________________________"
Clear

# is the output path syntax valid?
if (!(Test-Path -Path $MainSettings.OutputPath -IsValid)) {
    Write-Host -ForegroundColor Green "Output path syntax is invalid:" $MainSettings.OutputPath
    exit
    } else {
    Write-Host -ForegroundColor Green "Output path syntax is correct:" $MainSettings.OutputPath
    }

# does the output path exist?
if (!(Test-Path -Path $MainSettings.OutputPath)) {
    Write-Host -ForegroundColor Yellow "Output path does not exist:" $MainSettings.OutputPath
    [string]$CreateOutputPathOK=(Read-Host "[Y] to create the directory, [N] to quit.")
        if ($CreateOutputPathOK -ne "Y") {exit} else {New-Item -Path $MainSettings.OutputPath -ItemType Directory}
    } else {
    Write-Host -ForegroundColor Green "Output path already exists:" $MainSettings.OutputPath
}

Write-Host ""
Write-Host "______________________________________"
Clear

# get all .rpt files in the input folder, recursively
$CrystalFiles=Get-ChildItem -Path $CrystalSettings.InputFolderPath -Include "*.rpt" -Recurse

Write-Host ""
# count files first and ask the user if they want to see the output, otherwise proceed
Write-Host -ForegroundColor Yellow $CrystalFiles.Count ".rpt files were found in" $CrystalSettings.InputFolderPath
[string]$ShowFilesOK=(Read-Host "[Enter] to proceed, [Y] to view the list of files in the directory, [N] to quit.")
if ($ShowFilesOK -eq "Y") {
    Clear
    # loop through the collection of files and display the file path of each one
    $CrystalFiles | ForEach-Object -Process {$_.FullName.TrimStart($CrystalSettings.InputFolderPath)}
    Write-Host "______________________________________"
    # user must confirm
    Write-Host ""
    Write-Host -ForegroundColor Yellow "The above .rpt files were found in" $CrystalSettings.InputFolderPath 
} elseif ($ShowFilesOK -eq "N") {exit}

Write-Host ""
[string]$ProcessingOK=(Read-Host "[Y] to proceed with .rpt file processing, [N] to quit:")
if ($ProcessingOK -ne "Y") {exit}

Write-Host ""
Write-Host "______________________________________"
Clear

# create a dir inside the output path to hold this run's output
Write-Host -ForegroundColor Green "Creating folder to hold this run's output..."
$RunDir = (New-Item -Path $MainSettings.OutputPath -Name "$(Get-Date -f yyyy-mm-dd__hh_mm_ss)" -ItemType Directory)
$RunDir.FullName

# use .NET ArrayList because immutable PS arrays are very slow
$Success = New-Object System.Collections.ArrayList
$Failure = New-Object System.Collections.ArrayList

#loop through the collection again, this time processing each file and dumping the output to the output dir
$CrystalFiles | ForEach-Object -ErrorAction SilentlyContinue -Process {
    $RelativePathName = $_.FullName.TrimStart($CrystalSettings.InputFolderPath)
    $XmlFileName = "$RunDir\$RelativePathName.xml"

    # force-create the file to ensure the parent folder exists, otherwise RptToXML will crash trying to write the file
    New-Item -Path $XmlFileName -Force
    # then simply delete the empty file
    Remove-Item -Path $XmlFileName

    Write-Host -ForegroundColor Green "Processing file" $RelativePathName
    CMD /c .\RptToXML\RptToXml.exe $_.FullName $RunDir\$($_.FullName.TrimStart($CrystalSettings.InputFolderPath)).xml
    if ($LASTEXITCODE -eq 0) {
        Write-Host "Success" $Success.Add($RelativePathName)} else {Write-Host "Failure" $Failure.Add($RelativePathName)}
    }

$Success | Export-CSV "$RunDir\CrystalSuccess.txt"
$Failure | Export-CSV "$RunDir\CrystalFailure.txt"

最佳答案

我讨厌这样做,回答我自己的问题,但我现在找到了解决方法。

循环之前:

# Disable WER temporarily
Set-ItemProperty "HKCU:\Software\Microsoft\Windows\Windows Error Reporting" -Name DontShowUI -Value 1

循环后:

# Reset the WER UI reg key
Set-ItemProperty "HKCU:\Software\Microsoft\Windows\Windows Error Reporting" -Name DontShowUI -Value 0

这将通过从另一个脚本调用此脚本来改进:

  • 获取要修改的键的当前值
  • 改变它们
  • 调用将控制权返回给调用者的脚本,即使它崩溃了也是如此
  • 将注册键恢复为原来的值

关于windows - 从 Powershell 调用 .exe 时如何防止出现 "Program has stopped working"对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42163432/

相关文章:

windows-error-reporting - 有没有办法为 Windows 临时目录做一个 WER "Request Additional Files"?

java - 为什么读取目录时无法访问windows快捷方式

windows - 在批处理文件中删除目录树的最快方法

powershell - Azure 函数和 Powershell - 无法使用证书登录 AzureRmAccount

powershell - c 到 PowerShell 等效运算符的转换

c# - Windows 8.1 应用程序中的事件日志记录

c++ - 将特定的逻辑核心专门分配给特定的进程,Windows,C++

python - windows 的二进制 python 包(模块)的无人值守安装

c# - 带有哈希表/字典参数的 Powershell C# Cmdlet

windows - 抑制 'Excel has stopped working' 对话框