我编写了一个 PowerShell 脚本来打开文件夹及其子文件夹中的所有 PDF 文件。我知道某些 PDF 在打开时会出现 Adobe Acrobat Reader DC 错误。
该脚本的目标是打开目录(和子目录)内的所有 pdf 文件,并记录任何打开时出现错误的文件路径(成功打开的文件不应记录任何内容)。
我认为这是因为 PowerShell 成功打开了文件,本身没有错误;错误发生在 Adobe 方面。Adobe Acrobat Reader DC 显示的错误是:
Adobe Acrobat Reader DC could not open 'FileName' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).
是否可以使用 PowerShell 捕获这些 Adobe Acrobat Reader DC 错误?我当前的脚本如下:
$TargetPath = "C:\Users\User1\Desktop\Test.pdf"
$ErrorLog = "C:\Users\User1\Desktop\ErrorLog.txt"
Try
{
Get-ChildItem -Path $TargetPath *.pdf -Recurse | ForEach { Invoke-Item -Path $_.FullName }
}
Catch
{
"Error Opening $_.FullName" | Add-Content $ErrorLog
}
请注意,我是 PowerShell 的完全初学者,我根据从 Google 搜索中收集到的信息编写了此脚本。任何改进它的技巧都值得赞赏。
答案1
花时间来了解它真的很重要,以避免误解、错误、坏习惯等......
错误处理非常具体,具体到您要捕获的错误类型,甚至具体到您应该捕获的错误类型。 Try/catch 仅捕获终止错误。您收到的错误不是 Adobe 应用程序终止错误,不是 Adobe 打开,而只是文件打开错误。
PowerShell 教程 – Try Catch Finally 和 PowerShell 中的错误处理
强制错误停止 Windows PowerShell(而不是允许其继续执行下一行)的一种方法是将 ErrorAction 首选项从 Continue 更改为 Stop。我可以在 cmdlet 级别执行此操作。我使用 Get-ChildItem cmdlet 中的 –ErrorAction 自动参数(Dir 是别名),并将其更改为 Stop。这会导致错误终止 Windows PowerShell 执行并强制其进入 Catch 块。以下是更改:
Try {dir c:\missingFolder -ErrorAction Stop}
Catch [System.Exception] {"Caught the exception"}
Finally {$error.Clear() ; "errors cleared"}
OP 更新
至于……
无论如何,根据您的评论和链接,我无法弄清楚这种类型的“文件打开错误”是否可以在任何时候使用 PowerShell 将其识别为非终止错误。
... 如果您尝试捕获文件错误,则无法捕获,因为它从未打开,只有指定的应用程序打开了。即使打开尝试失败,Adobe 也会在其列表中加载错误的文件名。因此,您也不能为此使用 Invoke-Item。您必须使用调用的应用程序/进程名称。在本例中为 AcroRd32。
下面的代码可以工作,但你会注意到它永远不会像你那样在日志中写入文件名,但它会写入消息。如果你使用默认的 $Error 变量,你会得到更多。此外,始终避免使用保留的名称或非常接近 PowerShell 中保留变量的名称。这就是我向你指出额外培训的原因。
你的帖子中还有几件事不合逻辑。你传入一个文件名,但却对所有 pdf 文件进行目录搜索。为什么?这无论如何都行不通,因为有明确的单个文件请求。所以,根本不需要 ForEach,也不需要 Get-ChildItem。然而,请记住应用程序父级,在这种情况下,Adobe 将始终启动和加载,并且在打开失败时需要人工交互。
因此,你最终会到达这里:
$TargetPath = 'D:\Documents\B1UD8+QD0gS.pdf'
$TargetPath = 'E:\temp\TestBadPDF.pdf'
$ErrorLog = 'E:\temp\ErrorLog.txt'
Get-content -Path $ErrorLog
# What is in the log now
$Error.Clear()
# My new log
# Start the file
Invoke-Item -Path $TargetPath
# Get the process title
$ProcessHandle = (Get-Process -Name AcroRd32).MainWindowTitle
# Parse the file name
$FileName = (($TargetPath) -split '\\')[-1]
# Validate the process call
If ($ProcessHandle -eq "$($FileName) - Adobe Acrobat Reader DC")
{
# Custom success message
Add-Content -Path $ErrorLog -Value "Success Opening $TargetPath"
}
Else
{
# Custom error message
Add-Content -Path $ErrorLog -Value "Error Opening $TargetPath"
}
# Check the log
Get-content -Path $ErrorLog
# My new log
Success Opening D:\Documents\B1UD8+QD0gS.pdf
# repeat the process using a bad file
$TargetPath = 'E:\temp\TestBadPDF.pdf'
$ErrorLog = 'E:\temp\ErrorLog.txt'
Get-content -Path $ErrorLog
# My new log
Success Opening D:\Documents\B1UD8+QD0gS.pdf
$Error.Clear()
Invoke-Item -Path $TargetPath
$ProcessHandle = (Get-Process -Name AcroRd32).MainWindowTitle
$FileName = (($TargetPath) -split '\\')[-1]
If ($ProcessHandle -eq "$($FileName) - Adobe Acrobat Reader DC")
{
# Custom success message
Add-Content -Path $ErrorLog -Value "Success Opening $TargetPath"
}
Else
{
# Custom error message
Add-Content -Path $ErrorLog -Value "Error Opening $TargetPath"
}
Get-content -Path $ErrorLog
# My new log
Success Opening D:\Documents\B1UD8+QD0gS.pdf
Error Opening E:\temp\TestBadPDF.pdf