2013-09-19 1 views
0

Моя компания использует стороннюю DLL для взаимодействия с некоторыми аппаратными средствами (я переименовал ее hwLib здесь). Я думаю, это было написано давно в VB6. DLL поставляется с установщиком для регистрации и т. Д.Простая консольная консоль C++. 64-разрядная консоль Win7

У нас есть приложение C#, которое его использует и которое отлично работает на XP и Win7, 32 или 64 бит. Но я написал простой C++ консольное приложение, которое работает отлично на XP/32 бит, но падает на/64 bit.The консольного приложения Win7 выглядит так,

#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 COM object of type 'hwLib.ChwLibClass' to interface t ype 'hwLib._ChwLib'.

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

No such interface supported (Exception from HRE SULT: 0x80004002 (E_NOINTERFACE)). at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, Boolean& pfNeedsRelease) at hwLib.ChwLibClass.GetDllVersion() at main(String[] args) at mainCRTStartupStrArray(String[] arguments)

C# программа, которая намного больше и более сложную программу, иначе я бы разместил ее здесь, бежит без проблем в одной и той же системе.

COM до моего времени - я прошел курс в нем, возможно, 10 или 15 лет назад, но я не помню его - любое предложение о том, как начать отлаживать это? Благодаря!!

+1

Вы имеете в виду, что пытаетесь использовать 64-битное приложение CLR для доступа к 32-разрядной DLL? насколько мне известно, это невозможно - я не думаю, что вы сможете это сделать без компиляции в виде 32-битного. http://stackoverflow.com/questions/128445/calling-32bit-code-from-64bit-process http://stackoverflow.com/questions/2804818/ways-to-access-a-32bit-dll-from-a -64bit-ех –

ответ

4

COM предоставляет гарантии безопасности потока для COM-компонента, который заявляет, что не поддерживает резьбу. Любой компонент, написанный на VB6, безусловно, делает это. Режиссер записи в реестре с именем ThreadingModel.

Ваша тестовая программа не обеспечивает безопасный дом для такого компонента, приложение в консольном режиме создает многопоточную квартиру, MTA для краткости. Что обещает не обеспечить безопасность потока. Затем COM создает собственный поток STA для запуска кода для компонента. Каждый вызов компонента будет маршалирован из основного потока в этот вспомогательный поток.

Но тогда он натыкается на стену в вашем случае, ваш компонент не имеет зарегистрированного прокси-сервера. Дополнительный код, который COM должен выяснить, как скопировать аргументы метода. Легко в .NET благодаря Reflection, а не в COM. Прокси-сервер выбирается записями в разделе реестра HKCR \ Interface, компонент VB6 всегда использует стандартный маршаллер, который работает с библиотекой типов. Код ошибки E_NOINTERFACE для интерфейса IMarshal, последний вздох COM, чтобы найти способ, не реализованный VB6.

Неправильное получение права на регистрацию, бандажная помощь - позволить вашему консольному режиму создавать поток STA вместо потока MTA. Это не очень легко сделать, он просто принимает атрибут:

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

COM теперь уже не создает, что вспомогательный поток и вызовы не должны выстраивали. На самом деле этого недостаточно, поток STA также должен накачивать контур сообщения. Приложение :: Run(), как, вероятно, используется в вашей более крупной программе на C#. Цикл сообщений обеспечивает способ маршрутизации вызовов, очень похожий на Control.BeginInvoke() и Dispatcher.BeginInvoke(). Вы можете уйти от него, так как вы фактически не вызываете компоненты из другого потока. Но многие COM-компоненты полагаются на цикл сообщений, чтобы делать свои собственные вещи. Вы узнаете, что у вас есть проблема, когда вы видите тупик, или компонент не создает событие. Например, код VB6 может использовать таймер, он не будет отмечать без этого цикла сообщений.

Смежные вопросы