【问题标题】:Get MS-Word application instance using process handle使用进程句柄获取 MS-Word 应用程序实例
【发布时间】:2016-12-09 12:10:56
【问题描述】:

使用这个,

[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern IntPtr GetForegroundWindow();

然后我检索一个进程的句柄,

IntPtr hwnd = GetForegroundWindow();
int pid = APIFuncs.GetWindowProcessID(hwnd);
Process p = Process.GetProcessById(pid);
string appName = p.ProcessName;

所以每当我找到 appName = "WINWORD" 时,我想使用 hwnd

检索 Word 应用程序对象

注意:我不想创建新的 word 实例,只是运行一个。

【问题讨论】:

  • 对不起 Aniket,你能澄清你的问题吗

标签: c# ms-word vsto


【解决方案1】:

给定一个窗口句柄,您可以使用 oleacc.dll 中的 AccessibleObjectFromWindow 函数获得一个可自动化的 Word 应用程序实例。

这是一个示例程序,展示了如何使用它(添加对 Microsoft.Office.Interop.Word.dll 的引用):

using Microsoft.Office.Interop.Word;
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace WordLateBindingSample
{
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
    public interface IDispatch
    {
    }

    class Program
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("Oleacc.dll")]
        static extern int AccessibleObjectFromWindow(int hwnd, uint dwObjectID, byte[] riid, out IDispatch ptr);

        public delegate bool EnumChildCallback(int hwnd, ref int lParam);

        [DllImport("User32.dll")]
        public static extern bool EnumChildWindows(int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam);

        [DllImport("User32.dll")]
        public static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);

        public static bool EnumChildProc(int hwndChild, ref int lParam)
        {
            StringBuilder buf = new StringBuilder(128);
            GetClassName(hwndChild, buf, 128);
            if (buf.ToString() == "_WwG")
            {
                lParam = hwndChild;
                return false;
            }
            return true;
        }

        static void Main(string[] args)
        {
            // Use the window class name ("OpusApp") to retrieve a handle to Word's main window.
            // Alternatively you can get the window handle via the process id:
            // int hwnd = (int)Process.GetProcessById(wordPid).MainWindowHandle;
            //
            int hwnd = (int)FindWindow("OpusApp", null);

            if (hwnd != 0)
            {
                int hwndChild = 0;

                // Search the accessible child window (it has class name "_WwG") 
                // as described in http://msdn.microsoft.com/en-us/library/dd317978%28VS.85%29.aspx
                //
                EnumChildCallback cb = new EnumChildCallback(EnumChildProc);
                EnumChildWindows(hwnd, cb, ref hwndChild);

                if (hwndChild != 0)
                {
                    // We call AccessibleObjectFromWindow, passing the constant OBJID_NATIVEOM (defined in winuser.h) 
                    // and IID_IDispatch - we want an IDispatch pointer into the native object model.
                    //
                    const uint OBJID_NATIVEOM = 0xFFFFFFF0;
                    Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
                    IDispatch ptr;

                    int hr = AccessibleObjectFromWindow(hwndChild, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), out ptr);

                    if (hr >= 0)
                    {
                        var wordApp = (Application)ptr.GetType().InvokeMember("Application", BindingFlags.GetProperty, null, ptr, null);

                        var version = wordApp.Version;
                        Console.WriteLine(string.Format("Word version is: {0}", version));
                    }
                }
            }
        }
    }
}

【讨论】:

  • 在 Word 的情况下确实成功,但不幸的是我无法使用相同的代码检索 Outlook/Excel/Powerpoint。我们需要更改 Guid IID_IDispatch 吗?
  • @AniketBhansali:Excel 的示例可用here,本文末尾的 PowerPoint 示例:Launching Office Apps Programmatically
  • 谢谢,在 Excel 的情况下得到了解决方案,但没有获得 Powerpoint 和 Outlook 的可访问文档窗口类名称,我尝试将 paneClassDC 用于 Powerpoint,但无法正常工作。
  • msdn.microsoft.com/en-us/library/windows/desktop/… 的文档中没有提到 Outlook,所以我非常怀疑它是否受支持。仅支持 Word、Excel 和 PowerPoint
  • 有关其他信息,您可以将上述逻辑用于 Word、Excel 或 Access,但不能用于 Powerpoint 或 Outlook,因为它们的 COM 服务器是多用途(单实例)而不是 Word/Excel 的单用途(多实例) /访问,参考support.microsoft.com/en-us/help/316126/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 2015-03-07
  • 1970-01-01
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
相关资源
最近更新 更多