#c# #c #com
Вопрос:
У меня есть приложение C# .NET Framework, которое поставляется вместе с библиотекой DLL C#, имеющей COM-интерфейсы. Интерфейсы COM публикуются путем их регистрации в реестре Windows.
При запуске приложение C# запускает приложение C и устанавливает с ним связь (используя NamedPipes). Затем приложение C вызывает функцию из одного из зарегистрированных COM-интерфейсов.
Я добавил новую функцию в существующий интерфейс, заново скомпилировал все проекты, зарегистрировал обновленную библиотеку DLL в реестре Windows, и когда у меня все, как и раньше, работает совершенно нормально. Однако, когда я использую новую функцию, мое приложение C выходит из строя — и я не могу понять, почему.
В журнале событий Windows нет ошибки, и я знаю, что сбой происходит, когда я вызываю «_intf->FunctionV2». Вызов «_intf->Функция» работает нормально. Я добавил блок «попробуй поймать» вокруг него, но я ничего не поймал.
Есть какие-нибудь идеи?
try { _comClientAdapter->AddLog(L"Namespace::Function - pre", TRUE); result = _intf->FunctionV2(kontext, pCollection, TRUE); // result = _intf->Function(kontext, pCollection); _comClientAdapter->AddLog(L"Namespace::Function - post", TRUE); } catch (const std::overflow_erroramp; e) { std::wstringstream wss; wss << L"Namespace::Function - overflow_error - " << e.what(); _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (const std::runtime_erroramp; e) { std::wstringstream wss; wss << L"Namespace::Function - runtime_error - " << e.what(); _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (const std::exceptionamp; e) { std::wstringstream wss; wss << L"Namespace::Function - exception - " << e.what(); _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (std::string s) { std::wstringstream wss; wss << L"Namespace::Function - exception - " << s.c_str(); _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (std::wstring ws) { std::wstringstream wss; wss << L"Namespace::Function - exception - " << ws.c_str(); _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (int i) { std::wstringstream wss; wss << L"Namespace::Function - exception - " << i; _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (long l) { std::wstringstream wss; wss << L"Namespace::Function - exception - " << l; _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (unsigned long ul) { std::wstringstream wss; wss << L"Namespace::Function - exception - " << ul; _comClientAdapter->AddLog(wss.str().c_str(), TRUE); } catch (...) { _comClientAdapter->AddLog(L"Namespace::Function - exception - UNKNOWN", TRUE); IErrorInfo* pError; unsigned long result = GetErrorInfo(0, amp;pError); std::wstringstream wss; wss << L"Namespace::Function - exception - COM Error Result = "; if (SUCCEEDED(result) amp;amp; pError) { // Build an error message from the COM error object BSTR bstrSource = NULL; if (SUCCEEDED(pError->GetSource(amp;bstrSource)) amp;amp; bstrSource) { _bstr_t src(bstrSource, false); wss << static_cast<const char*>(src) << " : "; } BSTR bstrDesc = NULL; if (SUCCEEDED(pError->GetDescription(amp;bstrDesc)) amp;amp; bstrDesc) { wss << " - "; _bstr_t desc(bstrDesc, false); wss << static_cast<const char*>(desc); } } else { wss << L"GetErrorInfo failed"; } _comClientAdapter->AddLog(wss.str().c_str(), TRUE); }
Комментарии:
1. Вероятно, реестр COM находит старую версию библиотеки DLL C#, которая все еще реализует старую версию интерфейса. Вот почему в COM добавление новых функций обычно включает в себя наследование интерфейса, а не внесение изменений в существующие интерфейсы.
2. Если вы собираетесь изменить свои интерфейсы, сделайте себе одолжение и сделайте так, чтобы следующая добавляемая вами функция была очень простой и возвращала номер версии.
3. » Я добавил новую функцию в существующий интерфейс » — НЕ ДЕЛАЙТЕ ЭТОГО В COM! Как только интерфейс будет использоваться, НЕ ИЗМЕНЯЙТЕ ЕГО. Если вам нужно добавить функции или внести изменения в существующие функции, вместо этого добавьте их в качестве новых интерфейсов. Таким образом, существующие клиенты, которые не знают/заботятся о новых функциях/изменениях, не нуждаются в повторной компиляции, а новые клиенты, которые хотят использовать новые функции/изменения, могут просто запрашивать новые интерфейсы по мере необходимости. Это основная концепция стабильности COM, поэтому вам нужно следовать ей.
4. @RemyLebeau Я вынужден работать так, как хочет мой работодатель. Я не мог решить причину своей проблемы. Однако, когда я зарегистрировал DLL, созданную сервером сборки, она работала. Сейчас я не знаю ни источника проблемы, ни ее решения, но сейчас я могу работать.