从进程中获取当前打开的 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;
目标是获取在我有流程参考的 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;