Проблема - знатокам COM

Все, что вы хотели знать о программизме, но боялись спросить.
Ответить
Аватара пользователя
aldep
Маньяк
Сообщения: 1593
Зарегистрирован: 18 фев 2003, 08:06
Откуда: Toronto
Контактная информация:

Проблема - знатокам COM

Сообщение aldep »

Есть SAS OLEDB провайдер.
Простенькая функция

Код: Выделить всё

		ADODB::_ConnectionPtr adoConnection;
		adoConnection.CreateInstance(__uuidof(ADODB::Connection));
			
		adoConnection->Provider=L"sas.IOMProvider.1";
		ADODB::PropertyPtr spDSProp=adoConnection->Properties->Item[L"Data Source"];
		spDSProp->Value=L"_LOCAL_";
		adoConnection->Open("","","",ADODB::adModeUnknown);
		_bstr_t bsSQL;
		ADODB::_CommandPtr spCommand;
		spCommand.CreateInstance(__uuidof(ADODB::Command));
		spCommand->ActiveConnection=adoConnection;
		spCommand->CommandType=ADODB::adCmdText;

		bsSQL="libname mylib 'C:\\Alex\\Work\\TestSASProviders'";

		spCommand->CommandText=bsSQL;
		spCommand->Execute(&vtMissing,&vtMissing,ADODB::adCmdText);		
		ADODB::_RecordsetPtr adoInputRS;
		adoInputRS.CreateInstance(__uuidof(ADODB::Recordset));
		adoInputRS->Open("mylib.prediction_test",(IDispatch*)adoConnection,(ADODB::CursorTypeEnum),(ADODB::LockTypeEnum)3,0x200); //adOpenDynamic, adLockOptimistic, adCmdTableDirect

		ADODB::FieldPtr f=adoInputRS->Fields->GetItem(_variant_t(long(0)));
		f->Value=0;
		adoInputRS->UpdateBatch(ADODB::adAffectAll);

		adoConnection->Close();
Она вызывается из ATL COM out-of-proc сервера. Если она вызывается в Main, в конструкторе COM объекта или в FinalConstruct все проходит нормально, если же ее вызывать из метода этого СОМ объекта (сам метод взывается внешним скриптом), то при попытке выполнить adoInputRS->UpdateBatch
возвращается hr=0x800a0cb3 "Current Recordset does not support updating. This may be a limitation of the provider, or of the selected locktype."

Причем перед этим при исполнении f->Value=0; в дебаг аутпут выдается First-chance exception at 0x77e73887 in Worker.exe: 0x8001010E: The application called an interface that was marshalled for a different thread.

Когда исходная функция вызывается успешно (Main, Contructor или FinalConstruct) этого сообщения не наблюдается.

Вопрос очевидный - где собака порылась?
Woozy
Завсегдатай
Сообщения: 278
Зарегистрирован: 03 мар 2003, 08:55
Откуда: RU->BC->ON->FI -> Chicago, IL -> Seattle, WA

Re: Проблема - знатокам COM

Сообщение Woozy »

Сообщение hr=0x800a0cb3 "Current Recordset does not support updating. This may be a limitation of the provider, or of the selected locktype." не выглядит ошибкой использования COM.

Можно предположить, что в одном случае в контексте потока, в котором исполняется код был вызван CoInitialize(ex), в другом нет. Этот вызов зачастую "замаскирован" в коде ATL, что инициализирует модуль, но если отщепили поток, или вообще метод от этого объекта (он ведь из out-of-proc server) вызывается из потока другого процесса, то надо убедиться в наличии CoInitialize(ex) в том контексте. CoUnitialize соответственно по завершении того потока.

Другое трудно предпологать - отсюда не видно. У меня однажды было много радости с MS OLE for OLAP провайдером, когда я просто отщепил поток, но забыл выдать CoInitialize. Ошибки случались самые непредсказуемые - вроде 4-е вызова - Ok, 5-й - без видимых причин ломается и сообщение иногда казалось бы совсем "на другую тему". Поставил CoInitialize - CoUninitialize в начале - конце поточной функции - и всё заработало.
Аватара пользователя
aldep
Маньяк
Сообщения: 1593
Зарегистрирован: 18 фев 2003, 08:06
Откуда: Toronto
Контактная информация:

Сообщение aldep »

Не - CoinitializeEx стоял во всех потоках.
Вроде нашел в чем дело было.
Объект который вызывал САС код был объявлен как Free threaded и вызывал CoCreateFreeThreadedMarshaler.
Когда этот вызов был убран, все заработало.
Почему? Не знаю точно, если кто сможет объяснить, то буду благодарен.
Ответить