.NET Core C#中Acrobat关闭文件标签页时进程未终止问题求助
.NET Core C# 监听Acrobat标签页关闭事件的问题
我在.NET Core C#开发的应用中遇到下述问题:通过代码调用Acrobat打开PDF文件,当前监听Acrobat进程退出事件,关闭Acrobat主程序时可正常终止自身应用;但关闭Acrobat内的文件标签页时,应用仍在后台运行。我不想杀死所有Acrobat进程,希望获取文件标签页关闭的事件。
原代码示例
var process = Process.Start(new ProcessStartInfo { FileName = deafaultReader, Arguments = $"/n {filepath}", UseShellExecute = true }); process.EnableRaisingEvents = true; process.Exited += (sender, e) => { // 监听Acrobat关闭事件,在此处终止自身应用 }; return process; // 目前关闭Acrobat主程序时能正常终止应用,但关闭PDF标签页时,应用仍在后台运行
解决方案
Acrobat采用单进程多标签的架构,你启动的进程是主程序实例,关闭标签页不会触发主进程退出,因此靠Exited事件无法实现需求。以下是几种可行的解决思路:
1. 利用Acrobat COM接口监听文档关闭事件
Acrobat提供了COM自动化接口,可直接连接到Acrobat实例并监听文档关闭事件:
- 先在项目中添加COM引用,搜索并选择"Adobe Acrobat xx.0 Type Library"
- 编写监听代码:
using Acrobat; // 打开目标PDF并获取Acrobat实例 var acroApp = new CAcroApp(); var acroPDDoc = acroApp.Open(filepath, ""); // 绑定文档关闭事件 acroPDDoc.OnClose += () => { // 此处处理PDF标签页关闭逻辑,比如终止自身应用 Environment.Exit(0); }; // 注意:必须保持对acroApp和acroPDDoc的引用,否则会被GC回收导致监听失效
注意:该方式依赖Acrobat的COM支持,部分精简版Acrobat可能不提供此功能。
2. 轮询检查目标PDF窗口是否存在
如果无法使用COM接口,可通过Windows API枚举Acrobat窗口,轮询目标PDF的窗口标题是否存在:
using System.Runtime.InteropServices; using System.Timers; public class PdfWindowMonitor { [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); [DllImport("user32.dll")] private static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam); private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); private readonly string _targetPdfName; private Timer _checkTimer; public PdfWindowMonitor(string pdfFilePath) { _targetPdfName = Path.GetFileName(pdfFilePath); } public void StartMonitoring() { _checkTimer = new Timer(1000); // 每秒检查一次 _checkTimer.Elapsed += CheckPdfWindowStatus; _checkTimer.Start(); } private void CheckPdfWindowStatus(object sender, ElapsedEventArgs e) { bool isPdfOpen = false; EnumWindows((hWnd, lParam) => { var windowTitle = new StringBuilder(256); GetWindowText(hWnd, windowTitle, windowTitle.Capacity); string title = windowTitle.ToString(); // Acrobat窗口标题格式通常为"文件名 - Adobe Acrobat" if (title.Contains(_targetPdfName) && title.Contains("Adobe Acrobat")) { isPdfOpen = true; return false; // 找到目标窗口后停止枚举 } return true; }, IntPtr.Zero); if (!isPdfOpen) { _checkTimer.Stop(); _checkTimer.Dispose(); Environment.Exit(0); // 终止自身应用 } } } // 使用方式 var monitor = new PdfWindowMonitor(filepath); monitor.StartMonitoring();
注意:该方式依赖Acrobat窗口标题格式,若用户修改了Acrobat语言设置,需适配对应标题关键词。
3. 强制启动独立Acrobat实例
如果允许每个PDF打开独立的Acrobat进程,可修改启动参数,让每个PDF对应单独进程,这样关闭标签页(即进程退出)时就能触发Exited事件:
var process = Process.Start(new ProcessStartInfo { FileName = deafaultReader, Arguments = $"/s {filepath}", // 用/s参数强制启动新实例 UseShellExecute = true }); process.EnableRaisingEvents = true; process.Exited += (sender, e) => { Environment.Exit(0); }; return process;
注意:该方式会生成多个Acrobat进程,可能不符合用户常规使用习惯,但能直接复用原有的进程监听逻辑。
内容的提问来源于stack exchange,提问作者RAM yadav
相关产品推荐
相关产品推荐

