Вызов функции COM завершается сбоем, и я не могу понять, почему

#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, созданную сервером сборки, она работала. Сейчас я не знаю ни источника проблемы, ни ее решения, но сейчас я могу работать.