gpt4 book ai didi

c++ - 简单的 C++ .Net 控制台应用程序在 64 位 Win7 中崩溃

转载 作者:行者123 更新时间:2023-11-27 23:12:54 24 4
gpt4 key购买 nike

我的公司使用第 3 方 DLL 来连接某些硬件(我在这里将其重命名为 hwLib)。我认为它是很久以前用 VB6 编写的。 DLL 带有一个安装程序来注册自身等。

我们有一个使用它的 C# 应用程序,它在 XP 和 Win7(32 位或 64 位)上运行良好。但是我写了一个简单的 C++ 控制台应用程序,它在 XP/32 位上运行良好但在 Win7/64 位上崩溃。控制台应用程序看起来像这样,

#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
using namespace hwLib;
ChwLib^ myLib = gcnew ChwLib();
String^ str = myLib->GetDllVersion();
Console::WriteLine(L"Hello hwLib");
Console::WriteLine(str);
Console::ReadLine(); //to keep window open til you hit the "any" key
return 0;
}

Unhandled Exception: System.InvalidCastException: Unable to cast COMobject of type 'hwLib.ChwLibClass' to interface t ype 'hwLib._ChwLib'.

This operation failed because the QueryInterface call on the COMcomponent for the interface with IID'{E0560D1E-9A54-4EBF-83E8-D7BD2C936512}' failed due to the followingerror:

No such interface supported (Exception from HRE SULT:0x80004002 (E_NOINTERFACE)). atSystem.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtrpCPCMD, Boolean& pfNeedsRelease) athwLib.ChwLibClass.GetDllVersion() at main(String[] args) atmainCRTStartupStrArray(String[] arguments)

C# 程序,这是一个更大更复杂的程序,否则我会把它贴在这里,在同一系统上运行没有问题。

COM 出现在我之前 - 我可能在 10 或 15 年前参加过一门类(class),但我不记得了 - 关于如何开始调试它的任何建议?谢谢!!

最佳答案

COM 为声明自己不支持线程的 COM 组件提供线程安全保证。任何用 VB6 编写的组件都可以做到这一点。由注册表中名为 ThreadingModel 的条目引导。

您的测试程序没有为这样的组件提供一个安全的家,您的控制台模式应用程序创建了一个多线程单元,简称 MTA。 promise 提供线程安全。 COM 然后创建自己的 STA 线程来运行组件的代码。对组件的每次调用都将从主线程编码到该辅助线程。

但是在你的情况下它会遇到障碍,你的组件没有注册所需的代理/ stub 。 COM 需要确定如何复制方法参数的额外代码。由于反射,在 .NET 中很容易,而不是在 COM 中。代理/ stub 由 HKCR\Interface 注册表项中的条目选择,VB6 组件始终使用与类型库一起使用的标准编码器。 E_NOINTERFACE 错误代码是针对 IMarshal 接口(interface)的,这是 COM 寻找方法的最后喘息,不是由 VB6 实现的。

除了正确注册之外,创可贴是让您的控制台模式应用程序创建 STA 线程而不是 MTA 线程。这很容易做到,它只需要一个属性:

[STAThread]
int main(array<System::String ^> ^args)
// etc..

COM 现在不再创建辅助线程,调用也不必编码。这实际上还不够,一个 STA 线程还必须发送一个消息循环。 Application::Run() 可能在较大的 C# 程序中使用。消息循环提供了编码调用的方式,与 Control.BeginInvoke() 和 Dispatcher.BeginInvoke() 非常相似。你可能会侥幸逃脱,因为你实际上并没有从另一个线程调用组件。但是许多 COM 组件依赖于消息循环来完成它们自己的工作。当您看到死锁或组件未引发事件时,您就会知道您遇到了问题。例如,VB6 代码可以使用计时器,如果没有消息循环,它就不会计时。

关于c++ - 简单的 C++ .Net 控制台应用程序在 64 位 Win7 中崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18903783/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com