c#进程外Com服务(exe)编写调用

您所在的位置:网站首页 跨进程调用dll c#进程外Com服务(exe)编写调用

c#进程外Com服务(exe)编写调用

2023-08-25 16:54| 来源: 网络整理| 查看: 265

网上有些进程外的一些资料,但有些简单,研究了两天写了demo,可利用这种方式解决64位的程序调用32位的dll等问题,但注意方法参数不能含有IntPtr,因为指针跨进程是无效的,每个进程都有自己的内存区域

 一.编写外部Com服务exe     1.首先新建一个winform的应用程序,并设置com程序集可见

2.编写com类 

    编写com接口,guid可利用vs的工具生成,代码设置com接口的可视,实现接口后,编写com工厂启用com

  

internal static class ComHelperClass { public const string s_IID_ITestComVisible = "C66C0654-49AE-4f2e-8EDA-BD01C8259C20"; public const string s_CLSID_TestComVisibleClass = "12D783BB-33BF-4973-B38B-2A8F0BA926E4"; public static readonly Guid IID_ITestComVisible = new Guid(s_IID_ITestComVisible); public static readonly Guid CLSID_TestComVisibleClass = new Guid(s_CLSID_TestComVisibleClass); public const string s_IID_IClassFactory = "00000001-0000-0000-C000-000000000046"; public static readonly Guid IID_IClassFactory = new Guid("00000001-0000-0000-C000-000000000046"); public static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); [DllImport("ole32.dll")] public static extern int CoRegisterClassObject( [MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, [MarshalAs(UnmanagedType.IUnknown)] object pUnk, uint dwClsContext, uint flags, out uint lpdwRegister); [DllImport("ole32.dll")] public static extern int CoRevokeClassObject(uint dwRegister); [DllImport("ole32.dll")] public static extern int CoInitializeSecurity( IntPtr securityDescriptor, Int32 cAuth, IntPtr asAuthSvc, IntPtr reserved, UInt32 AuthLevel, UInt32 ImpLevel, IntPtr pAuthList, UInt32 Capabilities, IntPtr reserved3); public const int RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6; // Encrypted DCOM communication public const int RPC_C_IMP_LEVEL_IDENTIFY = 2; // No impersonation really required public const int CLSCTX_LOCAL_SERVER = 4; public const int REGCLS_MULTIPLEUSE = 1; public const int EOAC_DISABLE_AAA = 0x1000; // Disable Activate-as-activator public const int EOAC_NO_CUSTOM_MARSHAL = 0x2000; // Disable custom marshalling public const int EOAC_SECURE_REFS = 0x2; // Enable secure DCOM references public const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110); public const int E_NOINTERFACE = unchecked((int)0x80004002); } [ComVisible(true)] [Guid(ComHelperClass.s_IID_ITestComVisible)] public interface ITestComVisible { [DispId(1)] string TestProperty { get; set; } [DispId(2)] void TestMethod(); //可扩展相应的方法接口,并在TestComVisibleClass 实现 } [ComVisible(true)] [Guid(ComHelperClass.s_CLSID_TestComVisibleClass)] public class TestComVisibleClass : ITestComVisible { public string TestProperty { get; set; } public void TestMethod() { MessageBox.Show("我是32"); } } // 类厂 [ ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(ComHelperClass.s_IID_IClassFactory) ] internal interface IClassFactory { [PreserveSig] int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject); [PreserveSig] int LockServer(bool fLock); } internal class ComClassFactory : IClassFactory { #region IClassFactory Members public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject) { ppvObject = IntPtr.Zero; if (pUnkOuter != IntPtr.Zero) Marshal.ThrowExceptionForHR(ComHelperClass.CLASS_E_NOAGGREGATION); if (riid == ComHelperClass.IID_ITestComVisible || riid == ComHelperClass.IID_IUnknown) { ppvObject = Marshal.GetComInterfaceForObject( new TestComVisibleClass(), typeof(ITestComVisible)); } else Marshal.ThrowExceptionForHR(ComHelperClass.E_NOINTERFACE); return 0; // S_OK } public int LockServer(bool fLock) { return 0; // S_OK } #endregion } 3.编写代码启动com工厂,调用;并编译生成程序 static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); RegisterDcomServer(); Application.ApplicationExit += new EventHandler(Application_ApplicationExit); Application.Run(new Form1()); } static void Application_ApplicationExit(object sender, EventArgs e) { RevokeDcomServer(); } private static void RegisterDcomServer() { // 做一些安全检查,确保只有一些有权限的人才能调用你的C# Dcom组件 // 如果你对安全性不关心的话,可以删除下面的语句 //int hr = ComHelperClass.CoInitializeSecurity( // IntPtr.Zero, // 这里要输入你的安全描述符 // -1, // IntPtr.Zero, // IntPtr.Zero, // ComHelperClass.RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // ComHelperClass.RPC_C_IMP_LEVEL_IDENTIFY, // IntPtr.Zero, // ComHelperClass.EOAC_DISABLE_AAA | ComHelperClass.EOAC_SECURE_REFS | ComHelperClass.EOAC_NO_CUSTOM_MARSHAL, // IntPtr.Zero); //if (hr != 0) // Marshal.ThrowExceptionForHR(hr); int hr = ComHelperClass.CoRegisterClassObject( ComHelperClass.CLSID_TestComVisibleClass, new ComClassFactory(), ComHelperClass.CLSCTX_LOCAL_SERVER, ComHelperClass.REGCLS_MULTIPLEUSE, out m_ComCookie); if (hr != 0) Marshal.ThrowExceptionForHR(hr); } private static void RevokeDcomServer() { if (m_ComCookie != 0) ComHelperClass.CoRevokeClassObject(m_ComCookie); }      4.在本机注册com服务程序(管理身份运行 regasm)生成tlb文件,并修改添加注册表为本地服务(LocalServer32),删除自动生成的服务(inprocServer32)

查看系统注册表(建议使用RegWorkshop查看,检索guid )

vs使用的话到此就可以了,但如果c++调用的话还要在注册表里声明下tlb的信息

tlb信息可以用oleview进行查看,并在注册表添加信息

二、外部对com服务进行调用

    新建一个winform程序 ,编写调用代码,即可

        

System.Type t = Type.GetTypeFromProgID("TestComServer.TestComVisibleClass"); dynamic o = Activator.CreateInstance(t); o.TestMethod();

 至此我们的进程外com服务的编写和测试程序全部完成

完成的程序Demo 

注意下载Demo后,要现在本地进行com注册和相应注册表修改,如果感觉注册表操作麻烦,可以自己写个脚本

参考资料:

http://blog.csdn.net/zxdu721/article/details/7785277

https://www.cnblogs.com/killmyday/articles/1395432.html

https://www.codeproject.com/KB/COM/simplecomserver.aspx?display=Print



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3