Get Currently Opened Word Document from Process

1

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).

c#
winapi
com
office-interop
com-interop
asked on Stack Overflow Jan 18, 2018 by JDR • edited Jan 18, 2018 by Andy G

2 Answers

3

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);
}
answered on Stack Overflow Jan 18, 2018 by Andy G • edited Jan 18, 2018 by Andy G
0

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;
answered on Stack Overflow Jan 18, 2018 by Kalpesh Bhadra

User contributions licensed under CC BY-SA 3.0