电竞比分网-中国电竞赛事及体育赛事平台

分享

c#進程外Com服務(exe)編寫調用

 行走在理想邊緣 2022-05-06 發(fā)布于四川

網上有些進程外的一些資料,但有些簡單,研究了兩天寫了demo,可利用這種方式解決64位的程序調用32位的dll等問題,但注意方法參數(shù)不能含有IntPtr,因為指針跨進程是無效的,每個進程都有自己的內存區(qū)域

 一.編寫外部Com服務exe

    1.首先新建一個winform的應用程序,并設置com程序集可見


2.編寫com類 

    編寫com接口,guid可利用vs的工具生成,代碼設置com接口的可視,實現(xiàn)接口后,編寫com工廠啟用com


  

  1. internal static class ComHelperClass
  2. {
  3. public const string s_IID_ITestComVisible = "C66C0654-49AE-4f2e-8EDA-BD01C8259C20";
  4. public const string s_CLSID_TestComVisibleClass = "12D783BB-33BF-4973-B38B-2A8F0BA926E4";
  5. public static readonly Guid IID_ITestComVisible = new Guid(s_IID_ITestComVisible);
  6. public static readonly Guid CLSID_TestComVisibleClass = new Guid(s_CLSID_TestComVisibleClass);

  7. public const string s_IID_IClassFactory = "00000001-0000-0000-C000-000000000046";
  8. public static readonly Guid IID_IClassFactory = new Guid("00000001-0000-0000-C000-000000000046");
  9. public static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");

  10. [DllImport("ole32.dll")]
  11. public static extern int CoRegisterClassObject(
  12. [MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
  13. [MarshalAs(UnmanagedType.IUnknown)] object pUnk,
  14. uint dwClsContext,
  15. uint flags,
  16. out uint lpdwRegister);

  17. [DllImport("ole32.dll")]
  18. public static extern int CoRevokeClassObject(uint dwRegister);

  19. [DllImport("ole32.dll")]
  20. public static extern int CoInitializeSecurity(
  21. IntPtr securityDescriptor,
  22. Int32 cAuth,
  23. IntPtr asAuthSvc,
  24. IntPtr reserved,
  25. UInt32 AuthLevel,
  26. UInt32 ImpLevel,
  27. IntPtr pAuthList,
  28. UInt32 Capabilities,
  29. IntPtr reserved3);

  30. public const int RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6; // Encrypted DCOM communication
  31. public const int RPC_C_IMP_LEVEL_IDENTIFY = 2; // No impersonation really required
  32. public const int CLSCTX_LOCAL_SERVER = 4;
  33. public const int REGCLS_MULTIPLEUSE = 1;
  34. public const int EOAC_DISABLE_AAA = 0x1000; // Disable Activate-as-activator
  35. public const int EOAC_NO_CUSTOM_MARSHAL = 0x2000; // Disable custom marshalling
  36. public const int EOAC_SECURE_REFS = 0x2; // Enable secure DCOM references
  37. public const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110);
  38. public const int E_NOINTERFACE = unchecked((int)0x80004002);
  39. }

  40. [ComVisible(true)]
  41. [Guid(ComHelperClass.s_IID_ITestComVisible)]
  42. public interface ITestComVisible
  43. {
  44. [DispId(1)]
  45. string TestProperty { get; set; }

  46. [DispId(2)]

  47. void TestMethod();

  48. //可擴展相應的方法接口,并在TestComVisibleClass 實現(xiàn)

  49. }
  50. [ComVisible(true)]
  51. [Guid(ComHelperClass.s_CLSID_TestComVisibleClass)]
  52. public class TestComVisibleClass : ITestComVisible
  53. {
  54. public string TestProperty { get; set; }

  55. public void TestMethod()
  56. {
  57. MessageBox.Show("我是32");
  58. }
  59. }
  60. // 類廠
  61. [
  62. ComImport,
  63. InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
  64. Guid(ComHelperClass.s_IID_IClassFactory)
  65. ]
  66. internal interface IClassFactory
  67. {
  68. [PreserveSig]
  69. int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);
  70. [PreserveSig]
  71. int LockServer(bool fLock);
  72. }
  73. internal class ComClassFactory : IClassFactory
  74. {
  75. #region IClassFactory Members

  76. public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
  77. {
  78. ppvObject = IntPtr.Zero;
  79. if (pUnkOuter != IntPtr.Zero)
  80. Marshal.ThrowExceptionForHR(ComHelperClass.CLASS_E_NOAGGREGATION);
  81. if (riid == ComHelperClass.IID_ITestComVisible ||
  82. riid == ComHelperClass.IID_IUnknown)
  83. {
  84. ppvObject = Marshal.GetComInterfaceForObject(
  85. new TestComVisibleClass(), typeof(ITestComVisible));
  86. }
  87. else
  88. Marshal.ThrowExceptionForHR(ComHelperClass.E_NOINTERFACE);
  89. return 0; // S_OK
  90. }
  91. public int LockServer(bool fLock)
  92. {
  93. return 0; // S_OK
  94. }
  95. #endregion
  96. }


3.編寫代碼啟動com工廠,調用;并編譯生成程序

  1. static void Main()
  2. {
  3. Application.EnableVisualStyles();
  4. Application.SetCompatibleTextRenderingDefault(false);
  5. RegisterDcomServer();
  6. Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
  7. Application.Run(new Form1());
  8. }


  9. static void Application_ApplicationExit(object sender, EventArgs e)
  10. {
  11. RevokeDcomServer();
  12. }


  13. private static void RegisterDcomServer()
  14. {
  15. // 做一些安全檢查,確保只有一些有權限的人才能調用你的C# Dcom組件
  16. // 如果你對安全性不關心的話,可以刪除下面的語句
  17. //int hr = ComHelperClass.CoInitializeSecurity(
  18. // IntPtr.Zero, // 這里要輸入你的安全描述符
  19. // -1,
  20. // IntPtr.Zero,
  21. // IntPtr.Zero,
  22. // ComHelperClass.RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  23. // ComHelperClass.RPC_C_IMP_LEVEL_IDENTIFY,
  24. // IntPtr.Zero,
  25. // ComHelperClass.EOAC_DISABLE_AAA | ComHelperClass.EOAC_SECURE_REFS | ComHelperClass.EOAC_NO_CUSTOM_MARSHAL,
  26. // IntPtr.Zero);
  27. //if (hr != 0)
  28. // Marshal.ThrowExceptionForHR(hr);


  29. int hr = ComHelperClass.CoRegisterClassObject(
  30. ComHelperClass.CLSID_TestComVisibleClass,
  31. new ComClassFactory(),
  32. ComHelperClass.CLSCTX_LOCAL_SERVER,
  33. ComHelperClass.REGCLS_MULTIPLEUSE,
  34. out m_ComCookie);
  35. if (hr != 0)
  36. Marshal.ThrowExceptionForHR(hr);
  37. }


  38. private static void RevokeDcomServer()
  39. {
  40. if (m_ComCookie != 0)
  41. ComHelperClass.CoRevokeClassObject(m_ComCookie);

  42. }

     4.在本機注冊com服務程序(管理身份運行 regasm)生成tlb文件,并修改添加注冊表為本地服務(LocalServer32),刪除自動生成的服務(inprocServer32)



查看系統(tǒng)注冊表(建議使用RegWorkshop查看,檢索guid )



vs使用的話到此就可以了,但如果c++調用的話還要在注冊表里聲明下tlb的信息

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



二、外部對com服務進行調用

    新建一個winform程序 ,編寫調用代碼,即可

        

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

  3. o.TestMethod();

 至此我們的進程外com服務的編寫和測試程序全部完成

完成的程序Demo 

注意下載Demo后,要現(xiàn)在本地進行com注冊和相應注冊表修改,如果感覺注冊表操作麻煩,可以自己寫個腳本

參考資料:

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

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

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

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多