Get Currently Opened Word Document from Process

喜夏-厌秋 提交于 2021-02-10 18:21:52

问题


The goal is to get the full path to the document opened in an instance of Microsoft Word that I have a process reference for.

Pseudocode Example:

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

The starting point is a Process object which is executed by WINWORD.exe.

I am not looking for a way that includes parsing process.MainWindowTitle, but rather a more, let's say, "proper" solution.

Having done a fair bit of initial research, I believe what's required is the Windows Accessibility API.

Pinvoke mentiones the AccessibleObjectFromWindow signature. That being said, the resulting accessible object does not provide me with much more information than the process already does.

Here's what I tried from 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
    }
}

Perhaps the solution is to somehow get a Document interface (Office COM Interop, see here for the interface) from the process or window handle? Or, perhaps, first getting a Window and then the Document?

Then, equipped with that information from Office Interop, one could read the Path property.

I am open to any solutions for this.

If you know how to perform this regarding Excel or PowerPoint - then that would be fine, too, as I assume the same process can be applied for Word (after changing a couple of interfaces and GUIDs).


回答1:


Borrowing some code from Microsoft, the key method for which is 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);
            }
        }
    }
}

You still have a reference to the running process if you need it.

It is a simple matter to iterate the Documents collection if needed.

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



回答2:


You can get list of all word opened document using following code

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

Use following code to get active document full path

    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;


来源:https://stackoverflow.com/questions/48321167/get-currently-opened-word-document-from-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!