2010-02-04 5 views
4

Je développe du code dans C# où je vais interagir avec Microsoft Word. Je veux avoir la possibilité de réutiliser une instance existante ou de créer une nouvelle instance. En gardant à l'esprit que je veux faire tout cela en utilisant LATE BINDING ... il est sûr de dire que j'ai compris comment faire fonctionner les choses lors de la création d'une nouvelle instance .. J'appelle simplement Activator.CreateInstance etc.Comment accéder à l'instance existante de Microsoft Word en utilisant la liaison tardive

Le problème que je rencontre est de savoir comment réutiliser une instance existante, par exemple, Word est déjà ouvert et je veux utiliser cette instance.

Y a-t-il un Activator.UseExistingInstance? ou quelque chose de similaire ??

Merci!

+0

Salut, vous dites que vous créez un projet WinForms, et non une référence à la mise en Microsoft.Office.Interop.Word ou PIA, ou tout au moment de la conception? Dans ce cas, vous appelez quelque chose comme: Type.GetTypeFromProgID ("Word.Application"); et en utilisant Activator.CreateInstance sur ce type? En supposant que vous affectez le résultat d'Activator.CreateInstance à une variable de type objet 'var ou': quel est le problème de réutilisation de cette variable? – BillW

Répondre

4

Vous pouvez jeter un oeil à la fonction AccessibleObjectFromWindow définie dans Oleacc.dll. Andrew Whitechapel a quelques articles sur comment l'utiliser. Sur la base de ses articles que j'ai écrit une réponse à une question très similaire (environ Excel, pas Word), que vous pouvez trouver ici:

How to use use late binding to get Excel instance?

Vous y trouverez un exemple comment se connecter à une instance Excel en cours d'exécution, puis automatiser cette instance à l'aide d'une liaison tardive.

Mise à jour:

Voici un petit échantillon adapté à la Parole:

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) 
        { 
         object wordApp = ptr.GetType().InvokeMember("Application", BindingFlags.GetProperty, null, ptr, null); 

         object version = wordApp.GetType().InvokeMember("Version", BindingFlags.GetField | BindingFlags.InvokeMethod | BindingFlags.GetProperty, null, wordApp, null); 
         Console.WriteLine(string.Format("Word version is: {0}", version)); 
        } 
       } 
      } 
     } 
    } 
} 
+0

Je continue à obtenir 'hr = -2147467259', pouvez-vous s'il vous plaît aider @Dirk. –

+1

@AniketBhansali: que HRESULT signifie ["E_FAIL (erreur non spécifiée)"] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa378137%28v=vs.85%29.aspx). Dans quelle ligne l'obtenez-vous? –

+0

Je reçois cela comme résultat d'appeler 'AccessibleObjectFromWindow' dans la variable' hr' –

10

Vous cherchez Marshal.GetActiveObject.

object word; 
try 
{ 
    word = System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application"); 
} 
catch (COMException) 
{ 
    Type type = Type.GetTypeFromProgID("Word.Application"); 
    word = System.Activator.CreateInstance(type); 
} 
+0

Merci beaucoup. C'est la solution que je cherchais depuis longtemps. Meilleures salutations. – stexcec

+0

J'ai une poignée de processus, puis-je obtenir une instance de mot de cette poignée? –

Questions connexes