托管应用程序的 CoInitializeSecurity,创建垫片?

Posted

技术标签:

【中文标题】托管应用程序的 CoInitializeSecurity,创建垫片?【英文标题】:CoInitializeSecurity for managed application, creating a shim? 【发布时间】:2018-07-10 16:38:25 【问题描述】:

我目前正在研究将 com+ 安全上下文设置为:托管 winforms 进程的无。

在 .NET 中,不可能将 CoInitializeSecurity 设置为 Main 之后的第一行代码,为时已晚。据我了解,CLR 已经调用了该方法。

在下面的链接中: http://www.pinvoke.net/default.aspx/ole32.coinitializesecurity

上面写着:

“解决方法是编写一个将调用 CoInitializeSecurity 的非托管“shim”,然后激活并调用托管代码。您可以通过从混合模式 C++ DLL 导出,注册一个托管组件供以下人员使用来完成此操作COM,或使用 CLR 托管 API。”

有人能解释一下吗?应该如何用非托管代码编写(语言无关紧要)

托管应用程序时不时调用 com+ 服务器,我看不到 我应该立即激活界面以通过的任何理由 指向托管代码的指针?

【问题讨论】:

您发布的 PInvoke 链接中的代码示例按原样为我工作。您使用的是什么版本的 Visual Studio 和 .NET Framework?另外,请注意您引用的文本下方的更新:引用:“通常......在 CoInitializeSecurity 已经调用时发生(隐式或显式,这无关紧要)。当您使用 Visual Studio 时,它使用所谓的“Visual Studio Hosting已经调用 CoInitializeSecurity 的进程”。关闭 Visual Studio 托管进程并享受乐趣,现在您可以调试调用 CoInitializeSecurity 的应用程序,而不会出现 RPC_E_TOO_LATE 错误。” ".. CoInitialize 将 implicitly call CoInitializeSecurity 如果尚未调用..." - 在提供的链接中不正确 .请参考 MSDN doco 以及***.com/questions/30560589/… 【参考方案1】:

解决方法是编写一个将调用 CoInitializeSecurity 的非托管“shim”,然后激活并调用托管代码。您可以通过从混合模式 C++ DLL 导出、注册供 COM 使用的托管组件或使用 CLR 托管 API 来执行此操作。

这意味着您在 c/c++ 中创建了一个非常小的原生 .exe(“Shim”),它调用 CoInitializeEx(),然后调用 CoInitializeSecurity,作为建立 COM 安全环境的方法整个 Windows 进程。

 ----------------------------------
| Windows Process                  |
|  -----------         ----------  |
|  |   exe   |   COM   |  dll   |  |
|  | "Shim"  |  ====>  |        |  |
|  | (c/c++) |         |   c#   |  |
|  -----------         ----------  |
 -----------------------------------

代码:

// pseudo c++ code
.
.
.
int main (int argc, char* argv)

    CoInitializeEx(...);
    CoInitializeSecurity(...);

    IMyContractPtr pFoo (__uuidof (MyClass));
    pFoo->RunMe();

    CoUnitialize();

有了这些,下一个技巧是从 c/c++ 调用您的 .NET 代码。这里最简单的做法是创建一个ComVisible(True) c# 类,向 COM 公开一个方法,比如RunMe(),当调用它时会显示您的 WinForms 表单。

public interface IMyContractPtr 

    void RunMe();


[ComVisible(true)]  // there are cleaner ways to expose COM-visible 
public class MyClass : IMyContractPtr 

   public void RunMe()
   
       var form = new MainForm();
       form.ShowDialog(); // example
   

您需要将代码从 c# .exe 项目移动到新的 c# 程序集/库中。正是这个库将公开从您的 c/c++ 应用程序调用的 COM 可见类。 (尽管 c/c++ 应用程序不会关心它是在 COM exe 还是 dll 中,但对于这个练习,您不想通过尝试将另一个 .exe 加载到已经运行的 Windows 进程中来混淆问题)

消息泵和对话框

我通过使主窗口成为模态对话框来稍微简化了一些事情。模态对话框有自己的 Windows 消息泵处理,我们通过将您的表单代码放入 dll 并丢弃原始程序的 Main() 方法和 Application.Run(new MainForm()); 的优点,将其删除。

告诉我更多

How to call a managed DLL from native Visual C++ code

CoInitializeEx

CoInitializeSecurity

【讨论】:

难道不能启动本机 dll,设置 CoInitializeSecurity 并运行另一个进程,将“主机的”DCOM 安全设置传递给它吗? @John 可能不会。尽管可以将某些设置传递给子窗口进程(如窗口句柄),但我认为这不适用于 COM。此外,您不应调用 COM 初始化函数,包括库中的 CoInitializeSecurity

以上是关于托管应用程序的 CoInitializeSecurity,创建垫片?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用在托管资源组中具有权限的身份部署托管应用程序?

将托管控制托管为 CWnd 时应用程序挂起

一个解决方案中的非托管 DLL 项目和托管 WinForms 应用程序

托管和非托管的c++是啥意思,有啥区别?

无法从另一个托管引导程序应用程序卸载 WiX 托管引导程序应用程序

DebugBreak在非托管和混合(非托管+托管)应用程序之间有所不同?