如何在C#中识别和关闭已打开的应用程序的实例

时间:2012-05-09 12:48:14

标签: c# winforms acrobat

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

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

我尝试使用

获取进程列表
Process[] processes = Process.GetProcessesByName("AcroRd32");

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

  

有没有办法找到我的应用程序打开的Adobe阅读器实例。我只需要检查Adobe阅读器。没有任何其他。

更新

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

Four Process of reader

Last process with MainWindowTitle

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

您可以查看Process的MainWindowHandle属性。

答案 2 :(得分: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);
        }
    }

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

答案 3 :(得分: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正确地说这不是一个好的代码......)但我没有找到任何其他内容,遗憾...

(感谢Andrew Barber)