You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现Acrobat已打开PDF关闭、修改后重新打开问题求助

问题分析
  • 跨进程调用DestroyWindow无效:该API仅能销毁当前进程创建的窗口,关闭其他进程的窗口需要发送WM_CLOSE消息,模拟用户手动关闭窗口的行为
  • 仅存储PDF文件名无全路径:仅从窗口标题提取的文件名不包含路径信息,后续无法定位文件完成重新打开
  • 窗口匹配逻辑不严谨:没有过滤窗口所属进程,容易将其他带.pdf后缀标题的非Acrobat窗口误判
  • 无关闭完成校验:发送关闭消息后没有等待窗口完全销毁,直接运行修改程序可能仍存在文件占用
实现方案

核心优化点

  1. 先匹配Acrobat专属窗口类名AcrobatSDIWindow筛选目标窗口,避免误判
  2. 补充获取PDF全路径的逻辑,简单场景可直接拼接工作目录,复杂场景可枚举进程打开句柄获取
  3. 用SendMessageTimeout发送WM_CLOSE消息,等待窗口响应关闭
  4. 关闭完成后校验窗口存活状态,再启动修改程序,避免文件被占用
  5. 重新打开时调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 12:39:03