zoukankan      html  css  js  c++  java
  • .NET与COM互操作(1)绑定与com对象创建

    早期绑定

    即定义了强类型

    分两种方式
    1.使用工具自动生成
       1.1添加引用,则自动声明命名空间
       1.2运行TlbImp命令来声明,可修改命名空间

    2.手动编写,可以使用
      可调用部分com接口,无需全部声明,但非常麻烦

    以下为示例

    1.自动声明的代码

    可用实例或接口

    static void CreateInstanceByWrapper()
     {
         int num0 = 6, num1 = 4;
     
         SimpleCOMCalculatorClass calcObj = new SimpleCOMCalculatorClass();
     
         Console.WriteLine("运?算?:?{0} + {1} = {2}",
             num0, num1, calcObj.Add(num0, num1));
     
         Console.WriteLine("运?算?:?{0} - {1} = {2}",
             num0, num1, calcObj.Subtract(num0, num1));
     
         ISimpleCOMCalculator calcInterfaceObj = new SimpleCOMCalculatorClass();
     
         Console.WriteLine("运?算?:?{0} * {1} = {2}",
             num0, num1, calcInterfaceObj.Multiply(num0, num1));
     
         Console.WriteLine("运?算?:?{0} / {1} = {2}",
             num0, num1, calcInterfaceObj.Divide(num0, num1));
     
         int factorialResult = num1;
         calcInterfaceObj.Factorial(ref factorialResult);
         Console.WriteLine("运?算?:?!{0} = {1}",
                         num1, factorialResult);
     
     }

    2.自己手动创建代码

    虽然灵活,但容易出错,很麻烦,不推荐

    [ComImport]
       [Guid("C7386CE7-47B0-43C4-82D4-5FFA7A359EEA")]
       public class SimpleCOMCalculatorWrapper
       {
       }
     
       [ComImport]
       [CoClass(typeof(SimpleCOMCalculatorWrapper))]
       [Guid("FB1DE569-9B3D-491F-8EFC-25478CFBF172")]
       public interface ISimpleCOMCalculatorWrapper
       {
           [DispId(1)]
           int Add(int num0, int num1);
       }
     
       public class CreateInstanceByCustomeWrapperClass
       {
           public static void DoTest()
           {
               SimpleCOMCalculatorWrapper obj = new SimpleCOMCalculatorWrapper();
               ISimpleCOMCalculatorWrapper intf = obj as ISimpleCOMCalculatorWrapper;
               if (null != intf)
               {
                   int result = intf.Add(1, 2);
                   Console.WriteLine("\n用?自?定?义?包?装?类?创?建?COM对?象?。?计?算?器?:?+ 2 = {1}",
                       obj.GetType().Name, result);
               }
           }
       }


    后期绑定



    这个很好用,采用了反射技术,无需定义任何东西就可以调用com,由于是动态的,所以性能不比前期绑定的好.

    用Type的GetTypeFromProgID或GetTypeFromCLSID方法获取都可以

    static void Main(string[] Args)
     {
         // 通?过?ProgID返?回?COM对?象?类?型?
         Type comType = Type.GetTypeFromProgID(
             "SampleCOMSimple.SimpleCOMCalculator.1");
     
         // 也?可?以?通?过?CLSID返?回?COM对?象?类?型?
         //Guid clsid = new Guid("C7386CE7-47B0-43C4-82D4-5FFA7A359EEA");
         //Type comType = Type.GetTypeFromCLSID(clsid);
     
         // 创?建?COM对?象?实?例?
         Object comObj = Activator.CreateInstance(comType);
     
         // 设?置?方?法?参?数?
         Object[] methodArgs = { 6, 4 };
     
         // 调?用?加?法?
         Object result = comType.InvokeMember(
             "Add", BindingFlags.InvokeMethod, null,
             comObj, methodArgs);
     
         Console.WriteLine("运?算?:?{0} + {1} = {2}",
             methodArgs[0], methodArgs[1], result);
     
         // 调?用?减?法?
         result = comType.InvokeMember(
             "Subtract", BindingFlags.InvokeMethod, null,
             comObj, methodArgs);
     
         Console.WriteLine("运?算?:?{0} - {1} = {2}",
             methodArgs[0], methodArgs[1], result);
     
         // 调?用?乘?法?
         result = comType.InvokeMember(
             "Multiply", BindingFlags.InvokeMethod, null,
             comObj, methodArgs);
     
         Console.WriteLine("运?算?:?{0} * {1} = {2}",
             methodArgs[0], methodArgs[1], result);
     
         // 调?用?除?法?
         result = comType.InvokeMember(
             "Divide", BindingFlags.InvokeMethod, null,
             comObj, methodArgs);
     
         Console.WriteLine("运?算?:?{0} / {1} = {2}",
             methodArgs[0], methodArgs[1], result);
     
         // 调?用?阶?乘?方?法?
         // 由?于?参?数?需?要?从?方?法?中?返?回?结?果?,?要?使?用?ParameterModifier
         ParameterModifier paramMod = new ParameterModifier(1);
         paramMod[0] = true;
     
         int factorialArg = 4;
         Object[] methodArgs1 = { factorialArg };
         result = comType.InvokeMember(
             "Factorial", BindingFlags.InvokeMethod, null,
             comObj, methodArgs1, new ParameterModifier[] { paramMod },
             null, null);
         Console.WriteLine("运?算?:?!{0} = {1}",
                         factorialArg, methodArgs1[0]);
     
         Console.WriteLine("\r\n按?任?意?键?退?出?...");
         Console.Read();    
     }

    p/invoke创建com对象

    CoCreateInstance方法可以创建com对象,所以可以声明在托管代码中

    //STDAPI CoCreateInstance(
     //  REFCLSID rclsid,
     //  LPUNKNOWN pUnkOuter,
     //  DWORD dwClsContext,
     //  REFIID riid,
     //  LPVOID * ppv
     //);
     [DllImport("ole32.dll", ExactSpelling = true)]
     private static extern int CoCreateInstance(
         [In] ref Guid clsid,
         IntPtr pUnkOuter,
         uint context,
         [In] ref Guid iid,
         [Out] out IntPtr ppv);
     
     //HRESULT CLSIDFromProgID(
     //  LPCOLESTR lpszProgID,
     //  LPCLSID pclsid
     //);
     [DllImport("ole32.dll", ExactSpelling = true)]
     private static extern int CLSIDFromProgID(
         [MarshalAs(UnmanagedType.LPWStr)] string progid,
         ref Guid clsid);

    得到指针以后然后再将其转换为托管的com接口

    public static void DoTest()
            {
                Guid clsid = new Guid();
                int hr = CLSIDFromProgID("SampleCOMSimple.SimpleCOMCalculator.1", ref clsid);
                if (0 == hr) // S_OK
                {
                    Guid idispatch_id = new Guid("00020400-0000-0000-C000-000000000046");
                    IntPtr pIDispatch;
                    hr = CoCreateInstance(
                        ref clsid,
                        IntPtr.Zero,
                        1, // CLSCTX_INPROC_SERVER
                        ref idispatch_id,
                        out pIDispatch);
     
                    if (0 == hr)
                    {
                        object obj = Marshal.GetObjectForIUnknown(pIDispatch);
                        if (null != obj)
                        {
                            ISimpleCOMCalculator intf = obj as ISimpleCOMCalculator;
                            int result = intf.Add(1, 2);
                            Console.WriteLine("用?PInvoke创?建?COM对?象?。?计?算?器?:?+ 2 = {1}",
                                obj.GetType().Name, result);
                        }
                    }
                }
            }
  • 相关阅读:
    Plus One
    Move Zeroes
    Valid Number
    对于人生道路的些许感慨
    关于session.getValueNames()的一个问题
    jsp记录
    alter和modify的区别
    关于新手SQL Server 2008数据库的首次使用出现的问题
    今年大二,要开始java的学习了,听前辈说记录一下自己的学习过程会有一些好处
    MFC多文档无法显示可停靠窗格
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1809628.html
Copyright © 2011-2022 走看看