从进程中获取当前打开的 Word 文档

Get Currently Opened Word Document from Process

目标是获取在我有流程参考的 Microsoft Word 实例中打开的文档的完整路径。

伪代码示例:

Process myWordProcess = something; // This is my process reference
DocumentInformation docInfo = SomeNamespace.GetDocumentInformation(myWordProcess);
string documentPath = docInfo.FullName; // "C:\User\Foo\Documents\Test.docx"

起点是 Process 对象,由 WINWORD.exe 执行。

我不是在寻找一种包含解析 process.MainWindowTitle 的方法,而是在寻找更多 "proper" 解决方案。

经过大量初步研究,我认为需要的是 Windows 辅助功能 API。

Pinvoke 提到了 AccessibleObjectFromWindow 签名。话虽如此,生成的 accessible 对象并没有为我提供比 process 已经提供的信息更多的信息。

这是我从 Pinvoke 尝试的:

internal enum OBJID : uint
{
    WINDOW = 0x00000000,
    SYSMENU = 0xFFFFFFFF,
    TITLEBAR = 0xFFFFFFFE,
    MENU = 0xFFFFFFFD,
    CLIENT = 0xFFFFFFFC,
    VSCROLL = 0xFFFFFFFB,
    HSCROLL = 0xFFFFFFFA,
    SIZEGRIP = 0xFFFFFFF9,
    CARET = 0xFFFFFFF8,
    CURSOR = 0xFFFFFFF7,
    ALERT = 0xFFFFFFF6,
    SOUND = 0xFFFFFFF5,
}

public class DocumentLocator
{
    [DllImport("oleacc.dll")]
    internal static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint id, ref Guid iid, [In] [Out] [MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);

    public static void GetWordInfo(Process process)
    {
        var mainWindowHandle = process.MainWindowHandle;
        var guid = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");

        object obj = null;
        var retVal = AccessibleObjectFromWindow(mainWindowHandle, (uint)OBJID.WINDOW, ref guid, ref obj);
        var accessible = (IAccessible) obj; // Not much information is contained in this object
    }
}

也许解决方案是以某种方式获得 Document 接口(Office COM Interop,see here for the interface) from the process or window handle? Or, perhaps, first getting a Window 然后是 Document?

然后,利用 Office Interop 提供的信息,可以阅读 Path 属性。

我愿意接受任何解决方案。

如果您知道如何针对 Excel 或 PowerPoint 执行此操作 - 那也很好,因为我假设相同的过程可以应用于 Word(在更改几个界面和 GUID 之后) .

借鉴Microsoft的一些代码,关键方法是GetActiveObject:

using System;
using System.Runtime.InteropServices;
using Word = Microsoft.Office.Interop.Word;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            object wordAsObject;
            Word.Application word;

            try
            {
                wordAsObject = System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
                //If there is a running Word instance, it gets saved into the word variable
                word = (Word.Application)wordAsObject;

                Console.WriteLine("{0}", word.ActiveDocument.FullName);

                Console.ReadKey();
            }
            catch (COMException)
            {
                //If there is no running instance, it creates a new one
                //Type type = Type.GetTypeFromProgID("Word.Application");
                //wordAsObject = System.Activator.CreateInstance(type);
            }
        }
    }
}

如果需要,您仍然可以参考 运行 流程

如果需要,迭代 Documents 集合是一件简单的事情。

foreach (Word.Document doc in word.Documents)
{
    Console.WriteLine("{0}", doc.FullName);
}

您可以使用以下代码获取所有 word 打开文档的列表

Microsoft.Office.Interop.Word.Application WordObj;
WordObj = (Microsoft.Office.Interop.Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
for (int i = 0; i < WordObj.Windows.Count; i++)
{
    object idx = i + 1;
    Window WinObj = WordObj.Windows.get_Item(ref idx);
    doc_list.Add(WinObj.Document.FullName);
}

使用以下代码获取活动文档的完整路径

    Microsoft.Office.Interop.Word.Application WordObj;
    WordObj =
 (Microsoft.Office.Interop.Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
    var word = (Word.Application)WordObj;
    string docPath=word.ActiveDocument.FullName;