1

我只是使用 WebBrowser 控件在 WinForm 中加载 PDF 文件。我有一个 PDF 字节数组,当用户在我的应用程序中单击打印预览时,我曾经将它写在客户端机器的临时文件夹中。

在用户关闭表单时预览后,我需要删除文件。在删除之前,我需要关闭为预览打开的 Adob​​e Reader 实例。

我尝试使用获取进程列表

Process[] processes = Process.GetProcessesByName("AcroRd32");

我可以通过这种方式终止进程并从临时文件夹中删除文件。真正的问题来了。假设用户已经为自己的目的打开了一个 PDF 文件,然后通过找到正在运行的实例并关闭它们,我也会关闭他的阅读器。

有什么方法可以找到我的应用程序打开的 Adob​​e Reader 实例。我只需要检查 Adob​​e 阅读器。不是任何其他的。

更新

我已经手动打开了 adbobe 阅读器,它首先将文件名或 MainWindowTitle 作为 Magazine.pdf。然后我在我的应用程序中通过 webbrowser 控件打开了 adobe reader。但它的 MainWindowTitle 为 Empty。还应该有两个 adobe reader 实例,但在 taskmanager 中它显示四个实例,其中只有一个具有 MainWindowTitle 作为 Magazine.pdf 请参阅下图以供参考

阅读器的四个过程

MainWindowTitle 的最后一个进程

4

4 回答 4

1

检查每个 Acrobat 进程的 MainWindowTitle - 您想要的将以临时文件的名称开头。

于 2012-05-09T13:25:07.987 回答
0

如果要删除在 WebBrowser 控件中打开的 PDF 文件,则必须使用以下代码:

WebBrowser.Navigate(YourPdfPath)
...
WebBrowser.Navigate("about:blank")
Application.DoEvents()
Dim millisecondsTimeout = 5000
While True
  Try
    File.Delete(YourPdfPath)
    Exit While 
  Catch ex As IOException
    If millisecondsTimeout < 0 Then Exit Sub
    millisecondsTimeout -= 100
    Thread.Sleep(100)
  End Try
End While

更新:

我找到了一个扩展方法来杀死一个进程的子进程:

  <Extension>
  Public Sub KillChildren(process As Process, Optional processNameToKill As String = "", Optional recursive As Boolean = False)
      Static ProcessIDStack As List(Of Integer) = New List(Of Integer)
      If ProcessIDStack.Contains(process.Id) Then
          Exit Sub
      Else
          ProcessIDStack.Add(process.Id)
      End If

      Dim searcher = New ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" & process.Id) 'MLHIDE
      Dim moc As ManagementObjectCollection = searcher.Get
      For Each mo As ManagementObject In moc
          Try
              Dim ChildProcess = process.GetProcessById(Convert.ToInt32(mo("ProcessID"))) 'MLHIDE
              If recursive Then
                  ChildProcess.KillChildren(processNameToKill, recursive)
              End If
              If (Not ChildProcess.HasExited) AndAlso (processNameToKill = String.Empty OrElse ChildProcess.ProcessName = processNameToKill) Then
                  ChildProcess.Kill()
                  ChildProcess.WaitForExit(1000)
              End If
          Catch ex As ArgumentException
              ' process already exited 
          Catch ex As InvalidOperationException
              ' process already exited 
          Catch ex As ComponentModel.Win32Exception
              ' process already exited 
          End Try
      Next

      ProcessIDStack.Remove(process.Id)
  End Sub

...
    WebBrowser.Navigate("about:blank")
    Process.GetCurrentProcess.KillChildren("AcroRd32", True)
    Application.DoEvents()
...

我正在寻找一种更好的方法来检查文件是否未被使用,避免在循环中休眠(Andrew Barber 正确地说这不是一个好的代码......)但我没有找到其他任何东西,抱歉...... .

(感谢安德鲁·巴伯)

于 2012-09-06T10:35:40.323 回答
0

您可以查看 Process 的 MainWindowHandle 属性。

于 2012-05-09T12:51:58.187 回答
0

我没有使用 WebBrowser 打开 PDF,但是当我使用Process.MainWindowTitle(). 对于上次打开的 Acrobat 实例,它似乎只返回一个不同于 "" 的值。

我用来查找 Acrobat 的所有进程的 C# 代码如下:

  Process[] myProcess = Process.GetProcessesByName("AcroRd32");
  for (int i = 0; i < procesoProg.Length; i++)
  {
    if (myProcess[i].MainWindowTitle.Contains("MyTitle"))
    {
      myProcess[i].CloseMainWindow();
      Thread.Sleep(300);
    }
  }

我尝试使用Process.Kill()而不是Process.MainWindow(),但它会关闭所有 Acrobat 实例,而不仅仅是我想要的。

如果您只想关闭从应用程序打开的文档,您可以在启动 PDF 时存储该过程,并CloseMainWindow()在您想要关闭它时使用:

    private static Process myProcess = null;

    public void OpenPDF()
    {
        myProcess = new Process();
        myProcess.StartInfo.FileName = "AcroRd32.exe";
        myProcess.StartInfo.Arguments = " /n /A \"pagemode=bookmarks&nameddest=" + strND + "\" \"" + strPath + "\"";
        myProcess.Start();
    }

    public void ClosePDF()
    {
        // If there is 
        if (myProcess!= null)
        {
            myProcess.CloseMainWindow();
            Thread.Sleep(500);
        }
    }

我希望这段代码可以帮助你。

于 2012-05-17T14:16:14.647 回答