【问题标题】:How to identify and close an instance of opened application in C#如何在 C# 中识别和关闭打开的应用程序的实例
【发布时间】:2012-05-09 12:48:13
【问题描述】:

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

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

我尝试使用

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

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

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

更新

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

【问题讨论】:

  • 似乎无法识别它,因为当您从浏览器启动 Acrobat Viewer 时,它会在单独的域中运行。与其强行关闭它,为什么不向用户显示正在使用 pdf 文件的消息框。你想强制关闭它吗?如果他点击是然后关闭实例
  • 当用户关闭预览窗口时显示阅读器已打开的警报是否正确。如果他点击否,那么我如何关闭预览窗口
  • 不,我是说维护一个用于显示预览的标志,当用户关闭预览窗口时设置该标志,现在尝试删除它会给出异常,然后向用户显示正在使用 pdf 的消息通过其他程序我们应该关闭它吗?
  • 好的,没关系。但是如何关闭为预览打开的 Adob​​e 实例。我不想关闭所有打开的实例
  • 没有其他选择,这就是我们通知用户关闭实例的原因。

标签: c# winforms acrobat


【解决方案1】:

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

【讨论】:

  • 我的应用程序打开的实例的 MainWindowTitle 为 Empty。除此之外的任何时候它都会为空。
  • 它应该是临时文件的名称,我得看看你的代码,看看可能有什么问题。
【解决方案2】:

您可以查看 Process 的 MainWindowHandle 属性。

【讨论】:

  • MainHandleWindow 会返回任何东西来识别打开的实例
  • @Satheesh 您是否直接在表单中的 WebBrowser 控件中显示 pdf?我对你的理解正确吗?
  • 你是直接在 webbrowser 控件中显示 pdf
【解决方案3】:

我没有使用 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);
        }
    }

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

【讨论】:

    【解决方案4】:

    如果您想删除在 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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 2012-05-16
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多