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

如何用Selenium WebDriver按名称关闭指定文档?及特定Office文件关闭方法问询

How to Close a Specific Excel/Word Document by Name (Instead of Killing All Instances)

Hey there! Let's break down how to solve your problem—since WindowsUtils.killByName("excel.exe") wipes out every open Excel file, we need a more targeted approach.

First, a quick heads-up: Selenium WebDriver is built for browser automation, so it can't directly interact with desktop apps like Excel or Word. To handle Office documents, we'll use either Office COM Automation (the most reliable method) or target specific processes (only works if you configure Office to open each document in its own process).


This method directly talks to the Office application to close only the document you want. It preserves other open files and handles standard Office behaviors like save prompts properly.

Example for Excel (Java with Jacob Library)

Jacob lets you access Windows COM objects from Java. First, add the Jacob library to your project (you'll need the JAR and matching 32/64-bit DLL):

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class SpecificOfficeDocClosure {
    public static void closeTargetExcel(String targetDocName) {
        ActiveXComponent excelApp = new ActiveXComponent("Excel.Application");
        try {
            // Set to true if you need to see the Excel window; false works too
            excelApp.setProperty("Visible", new Variant(true));
            
            Dispatch workbooks = excelApp.getProperty("Workbooks").toDispatch();
            int workbookCount = Dispatch.call(workbooks, "Count").getInt();
            
            // Loop backwards to avoid skipping items when closing
            for (int i = workbookCount; i >= 1; i--) {
                Dispatch workbook = Dispatch.call(workbooks, "Item", new Variant(i)).toDispatch();
                String currentDocName = Dispatch.call(workbook, "Name").getString();
                
                if (currentDocName.equals(targetDocName)) {
                    // Close without saving (pass true to save changes)
                    Dispatch.call(workbook, "Close", new Variant(false));
                    break;
                }
            }
        } finally {
            // Don't quit the entire Excel app—just release the COM object
            excelApp.safeRelease();
        }
    }

    public static void main(String[] args) {
        closeTargetExcel("Q4_Sales.xlsx");
    }
}

Example for Word (Python with pywin32)

If you prefer Python, the pywin32 library makes COM interactions straightforward:

import win32com.client

def close_target_word(target_doc_name):
    try:
        word_app = win32com.client.GetActiveObject("Word.Application")
        for doc in word_app.Documents:
            if doc.Name == target_doc_name:
                # Close without saving (change to True to save)
                doc.Close(SaveChanges=False)
                break
    except Exception as e:
        print(f"Error closing document: {e}")

# Call the function
close_target_word("Project_Proposal.docx")

Option 2: Target Specific Processes (Only for Single-Document Office Processes)

By default, Office opens all documents in one process. If you change this setting (File > Options > Advanced > "Don't allow multiple instances of Excel"), each document gets its own process. Then you can find the process linked to your target document and terminate it.

Java Example with JNA

This uses JNA to query process command lines (which include the document path):

import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Psapi;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;

import java.util.ArrayList;
import java.util.List;

public class OfficeProcessKiller {
    public static List<WinNT.HANDLE> findOfficeProcessesByDoc(String processName, String docName) {
        List<WinNT.HANDLE> targetProcesses = new ArrayList<>();
        WinDef.DWORDByReference processIds = new WinDef.DWORDByReference();
        int bytesReturned = 0;

        // Get all running process IDs
        if (!Psapi.INSTANCE.EnumProcesses(processIds.getPointer(), new WinDef.DWORD(1024), new WinDef.DWORDByReference(new WinDef.DWORD(bytesReturned)))) {
            return targetProcesses;
        }

        int numProcesses = bytesReturned / Kernel32.INSTANCE.GetNativeLongSize();
        int[] pids = processIds.getPointer().getIntArray(0, numProcesses);

        for (int pid : pids) {
            WinNT.HANDLE processHandle = Kernel32.INSTANCE.OpenProcess(
                WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, 
                false, 
                pid
            );

            if (processHandle != null) {
                char[] pathBuffer = new char[1024];
                if (Psapi.INSTANCE.GetProcessImageFileName(processHandle, pathBuffer, new WinDef.DWORD(pathBuffer.length)) > 0) {
                    String exePath = new String(pathBuffer).trim();
                    if (exePath.endsWith(processName)) {
                        // Check if the command line includes the target document
                        char[] cmdBuffer = new char[4096];
                        if (Psapi.INSTANCE.GetCommandLine(processHandle, cmdBuffer, new WinDef.DWORD(cmdBuffer.length)) > 0) {
                            String cmdLine = new String(cmdBuffer).trim();
                            if (cmdLine.contains(docName)) {
                                targetProcesses.add(processHandle);
                            } else {
                                Kernel32.INSTANCE.CloseHandle(processHandle);
                            }
                        }
                    } else {
                        Kernel32.INSTANCE.CloseHandle(processHandle);
                    }
                }
            }
        }
        return targetProcesses;
    }

    public static void terminateProcesses(List<WinNT.HANDLE> processes) {
        for (WinNT.HANDLE handle : processes) {
            Kernel32.INSTANCE.TerminateProcess(handle, 0);
            Kernel32.INSTANCE.CloseHandle(handle);
        }
    }

    public static void main(String[] args) {
        List<WinNT.HANDLE> excelProcesses = findOfficeProcessesByDoc("excel.exe", "Q4_Sales.xlsx");
        terminateProcesses(excelProcesses);
    }
}

Key Takeaways

  • COM Automation is best: It's the official way to interact with Office, avoids closing unrelated files, and respects Office's built-in logic.
  • Process killing is a fallback: Only use this if you've configured Office to run each document in a separate process, and be aware it will force-close the document (no save prompts).

内容的提问来源于stack exchange,提问作者Jagadeesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:40:43