Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

C#で実行時に得たCOMオブジェクトのインタフェース名を取得する

やれること

インスタンス化したComObject(※)が特定のインタフェース(IDispatch)を実装している場合に

  • インタフェース名 と そのGUID
  • TypeLibrary名

を取得します。

※簡単な判別方法: .GetType().ToString()"System.__ComObject"になるやつ

ソースコード

ソースコード

using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.InteropServices;

// ↓これを消すと、System.Runtime.InteropServicesにある同名の古い定義をうっかり引き当ててしまうおそれがあるので残す
using System.Runtime.InteropServices.ComTypes;

using ComTypes = System.Runtime.InteropServices.ComTypes;


public static class ShowComInfo
{
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-c000-000000000046")]
    private interface IDispatch
    {
        [PreserveSig]
        int GetTypeInfoCount(out int count);
        [PreserveSig]
        int GetTypeInfo([In] int itinfo, [In] int lcid, out IntPtr typeinfo);
        [PreserveSig]
        int GetIDsOfNames();//dummy. don't call this method
        [PreserveSig]
        int Invoke();//dummy. don't call this method
    }

    static Guid? GetGuidFromIType(ITypeInfo typ)
    {
        Guid? guid = null;
        IntPtr ptr;
        try {
            typ.GetTypeAttr(out ptr);
        }
        catch ( COMException ) { return null; }

        try {
            var attr = Marshal.PtrToStructure<ComTypes.TYPEATTR>(ptr);
            guid = attr.guid;
        }
        finally {
            typ.ReleaseTypeAttr(ptr);
        }

        return guid;
    }

    static void ShowNamesOfTypeInfo(ITypeInfo typ)
    {
        string strName;
        string strDocString;
        int dwHelpContext;
        string strHelpFile;

        typ.GetDocumentation(-1, out strName, out strDocString, out dwHelpContext, out strHelpFile);
        Console.Write("InterfaceName: ");
        Console.WriteLine(strName??"<<NULL>>");
        Console.Write("InterfaceDocString: ");
        Console.WriteLine(strDocString??"<<NULL>>");
        Console.Write("InterfaceHelpFile: ");
        Console.WriteLine(strHelpFile??"<<NULL>>");
    }

    static void ShowNamesOfTypeLib(ITypeLib typ)
    {
        string strName;
        string strDocString;
        int dwHelpContext;
        string strHelpFile;

        typ.GetDocumentation(-1, out strName, out strDocString, out dwHelpContext, out strHelpFile);
        Console.Write("TypeLibName: ");
        Console.WriteLine(strName??"<<NULL>>");
        Console.Write("TypeLibDocString: ");
        Console.WriteLine(strDocString??"<<NULL>>");
        Console.Write("TypeLibHelpFile: ");
        Console.WriteLine(strHelpFile??"<<NULL>>");
    }

    public static void ShowInterfaceIdFromComObject(object obj)
    {
        Guid? guid = null;
        ComTypes.ITypeInfo typeInfo = null;
        IntPtr ptr = IntPtr.Zero;

        try {
            if ( obj is IDispatch ) {
                var idisp = (IDispatch)obj;
                int count;
                int hResult = idisp.GetTypeInfoCount(out count);
                if ( hResult >= 0 ) { // Succeeded
                    if ( count < 1 ) { // no type info
                        return;
                    }

                    idisp.GetTypeInfo(0, 0, out ptr);
                    if ( ptr == IntPtr.Zero ) {
                        return;
                    }

                    typeInfo = (ComTypes.ITypeInfo)
                       (Marshal.GetTypedObjectForIUnknown(ptr, typeof(ComTypes.ITypeInfo)));

                    if ( typeInfo == null ) {
                        return;
                    }
                    ShowNamesOfTypeInfo(typeInfo);
                    guid = GetGuidFromIType(typeInfo);
                    Console.Write("InterfaceGUID: ");
                    Console.WriteLine(guid);

                    ITypeLib typLib;
                    int indexOfLib;
                    typeInfo.GetContainingTypeLib(out typLib, out indexOfLib);
                    ShowNamesOfTypeLib(typLib);
                }
            }
            else { // unknown type
                return;
            }
        }
        finally {
            if ( ptr != IntPtr.Zero ) {
                Marshal.Release(ptr);
                ptr = IntPtr.Zero;
            }
        }
    }
}

class Test
{
    [STAThread]
    static void Main(string[] args)
    {
        Type comType = Type.GetTypeFromProgID("Shell.Application");
        dynamic o = Activator.CreateInstance(comType);

        try {
            ShowComInfo.ShowInterfaceIdFromComObject(o);
        }
        finally {
            Marshal.ReleaseComObject(o);
        }
    }
}

実行結果

InterfaceName: IShellDispatch6
InterfaceDocString: Updated IShellDispatch
InterfaceHelpFile: <<NULL>>
InterfaceGUID: 34936ba1-67ad-4c41-99b8-8c12dff1e974
TypeLibName: Shell32
TypeLibDocString: Microsoft Shell Controls And Automation
TypeLibHelpFile: <<NULL>>

ちなみにCOMオブジェクトのインタフェースは、レジストリの HKEY_CLASSES_ROOT\Interface にいます。
OleView.exeでTypeLibraryを探すと情報がみれる。

参考サイト

OleView.exeの使い方

OleView.exeでインタフェースのメソッド、プロパティを調べる方法。
※そのPCにインストールされているものしか出ません。例:ExcelがインストールされていないPCでExcelのCOM Objectは多分でてこない。

■Step0. 入手する ・・・ oleview.exe microsoft あたりのキーワードでググるべし。
■Step1. 起動する ・・・ C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin らへんにいるはず。。環境依存。
image.png
■Step2. タイプライブラリ名を探す
「Type Libraries」から、TypeLib名を探す(例:Microsoft Shell Controls And Automation)
■Step3. タイプライブラリ名をダブルクリックする
・・・別ウィンドウが立ち上がります。
■Step4. インタフェース名を探す。
・・・dispinterface インタフェース名

その後

C#でITypeInfoクラスを使い倒してCOMオブジェクトの関数名とパラメータを表示させる

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?