从Process获取当前打开的Word文档

时间:2018-01-18 12:17:42

标签: c# winapi com office-interop com-interop

目标是获取在我有过程参考的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,而是更多,让我们说,“正确”的解决方案。

我做了一些初步的研究,我相信所需要的是Windows Accessibility 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)?或者,也许首先获得Window然后获得Document

然后,配备来自Office Interop的信息,可以阅读Path属性。

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

如果你知道如何在Excel或PowerPoint上执行此操作 - 那么这也没关系,因为我假设可以对Word应用相同的过程(在更改几个接口和GUID之后)。

2 个答案:

答案 0 :(得分:3)

借用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);
}

答案 1 :(得分:0)

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

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;