0

質問は次のスレッドに関連しています: Access COM vtable from C#

私がしなければならないことは、C# のメソッド ポインターを介して com オブジェクトからメソッドを呼び出すことです。

メソッドポインターが必要ないことはわかっていますが、この特別な場合は必要です。

なぜメソッドポインタが必要なのですか?

遅延バインディングを介して Word.Content コントロールから SetPlaceholderText メソッドにアクセスしたい。.NET->COM のすべての latebind 機能は、com オブジェクトから実装された IDispatch インターフェイスの Invoke メソッドを使用します。Word.ContentControl クラスの Invoke メソッドにバグがあります。相互運用ランタイムが呼び出しを回避し、メソッドポインターを使用するため、早期バインドが機能します。(それは私も問題を処理したいものです)。vb latebinding、c# ダイナミクス、または GetType().Invoke でメソッドを使用することは不可能です...

リンクされた投稿のコードをテンプレートとして使用します。

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void SetPlaceHolderTextCallback(
      [MarshalAs(28)] [In] object BuildingBlock = null,
      [MarshalAs(28)] [In] object Range = null, 
      [MarshalAs(19)] [In] string Text = "");

object contentControl = GetContentControlProx();
IntPtr comPtr = Marshal.GetComInterfaceForObject(contentControl,
                                         typeof(ContentControl));
IntPtr vTable = Marshal.ReadIntPtr(comPtr); 

int start = Marshal.GetStartComSlot(typeof(ContentControl));
int end = Marshal.GetEndComSlot(typeof(ContentControl));

SetPlaceHolderTextCallback invoker = null;
ComMemberType mType = MemberTypes.Method;
for (int i = start; i < end; i++)
{
   System.Reflection.MemberInfo mi = 
   Marshal.GetMethodInfoForComSlot(typeof(ContentControl), i, ref mType);
   if (mi.Name == "SetPlaceholderText")
   {
      IntPtr methodPointer = Marshal.ReadIntPtr(vTable, i * 
                                  Marshal.SizeOf(typeof(IntPtr)));
      invoker = Marshal.GetDelegateForFunctionPointer(methodPointer,
      typeof(SetPlaceHolderTextCallback)) as SetPlaceHolderTextCallback;
      break;
   }
}

invoker(Type.Missing, Type.Missing, "helloWorld");

呼び出しは AccessViolationException で失敗します。現時点ではわかりません....

4

1 に答える 1

0

私の問題は解決したようです。jochen manns のブログ エントリに答えがあります。最初のパラメーターは、クラス インスタンスへの IntPtr でなければなりません。

<!-- language: lang-cs -->
    IntPtr adressPointer = Marshal.GetComInterfaceForObject(control, 
                                    typeof(Word.ContentControl));
    invoker(adressPointer, null, null, "helloWorld");
<!-- language: lang-cs -->

動作します!!!

于 2013-02-07T05:57:22.930 に答える