C语言实现Acrobat已打开PDF关闭、修改后重新打开问题求助
问题分析
- 跨进程调用
DestroyWindow无效:该API仅能销毁当前进程创建的窗口,关闭其他进程的窗口需要发送WM_CLOSE消息,模拟用户手动关闭窗口的行为 - 仅存储PDF文件名无全路径:仅从窗口标题提取的文件名不包含路径信息,后续无法定位文件完成重新打开
- 窗口匹配逻辑不严谨:没有过滤窗口所属进程,容易将其他带
.pdf后缀标题的非Acrobat窗口误判 - 无关闭完成校验:发送关闭消息后没有等待窗口完全销毁,直接运行修改程序可能仍存在文件占用
实现方案
核心优化点
- 先匹配Acrobat专属窗口类名
AcrobatSDIWindow筛选目标窗口,避免误判 - 补充获取PDF全路径的逻辑,简单场景可直接拼接工作目录,复杂场景可枚举进程打开句柄获取
- 用
SendMessageTimeout发送WM_CLOSE消息,等待窗口响应关闭 - 关闭完成后校验窗口存活状态,再启动修改程序,避免文件被占用
- 重新打开时调用
ShellExecute关联系统默认PDF阅读器打开文件
完整代码示例
#include <windows.h> #include <stdio.h> #include <shellapi.h> #pragma comment(lib, "shell32.lib") #define MAX_PDF_COUNT 16 char pdf_paths[MAX_PDF_COUNT][MAX_PATH]; // 存储PDF全路径 int pdf_count = 0; // 枚举窗口回调 BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { char class_name[256]; char title[256]; // 先匹配Acrobat窗口类名 GetClassName(hwnd, class_name, sizeof(class_name)); if (strcmp(class_name, "AcrobatSDIWindow") != 0) { return TRUE; } // 匹配窗口标题是否带.pdf后缀 GetWindowText(hwnd, title, sizeof(title)); int title_len = strlen(title); if (title_len < 5 || strcmp(&title[title_len - 4], ".pdf") != 0) { return TRUE; } // 简单场景示例:假设所有PDF均在当前工作目录,直接拼接路径 GetCurrentDirectory(MAX_PATH, pdf_paths[pdf_count]); strcat(pdf_paths[pdf_count], "\\"); strcat(pdf_paths[pdf_count], title); // 存储窗口句柄用于关闭 HWND* h_wnds = (HWND*)lParam; h_wnds[pdf_count] = hwnd; pdf_count++; return pdf_count < MAX_PDF_COUNT; } void close_pdfs() { pdf_count = 0; HWND h_wnds[MAX_PDF_COUNT] = {0}; EnumWindows(EnumWindowsProc, (LPARAM)h_wnds); // 逐个发送关闭消息 for (int i = 0; i < pdf_count; i++) { SendMessageTimeout(h_wnds[i], WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 3000, NULL); } // 等待所有窗口关闭,最长等待10秒 int wait_cnt = 0; while (wait_cnt < 10) { int all_closed = 1; for (int i = 0; i < pdf_count; i++) { if (IsWindow(h_wnds[i])) { all_closed = 0; break; } } if (all_closed) break; Sleep(1000); wait_cnt++; } } void reopen_pdfs() { for (int i = 0; i < pdf_count; i++) { // 调用系统默认PDF阅读器打开文件 ShellExecute(NULL, "open", pdf_paths[i], NULL, NULL, SW_SHOWNORMAL); } } // 调用逻辑示例 int main() { close_pdfs(); system("modify_pdfs.exe"); reopen_pdfs(); return 0; }
注意事项
- 上述代码中获取PDF全路径的逻辑为简化版,仅适用于PDF在当前工作目录的场景。如果需要适配任意路径的PDF,可引入
NtQuerySystemInformation枚举进程打开的文件句柄,筛选后缀为.pdf的文件即可获取全路径。 - 如果使用的是多标签版Acrobat,可通过发送菜单消息的方式逐个关闭标签,或者直接结束Acrobat进程再重启恢复会话。
内容的提问来源于stack exchange,提问作者Miyagi's Car Wash
相关产品推荐
相关产品推荐

