Я пытаюсь использовать автоматизацию Ole PCAnywhere в приложении .net, которое я сейчас разрабатываю (VS 2010, C #). PCA 12.5 поставляется с парой файлов tlb, которые, когда я пытаюсь добавить в качестве ссылок через VS, я получаю сообщение об ошибке: «Не удалось добавить ссылку на E: \ Dev \ PcaOle \ awrem32.tlb». Убедитесь, что файл доступен и является допустимой сборкой или компонентом COM. ', Поэтому я сгенерировал сборки взаимодействия с помощью tlbimp.exe и без проблем смог импортировать созданные библиотеки DLL в качестве ссылок. В ПОРЯДКЕ. Вот фрагмент кода, который у меня есть:
Thread pcat = new Thread(delegate()
{
CRemoteDataManagerClass mng = new CRemoteDataManagerClass();
RemoteDataExClass data = null;
data = (RemoteDataExClass)mng.RetrieveObjectEx("temp.chf", (short)2, null);
if (data == null)
data = (RemoteDataExClass)mng.CreateObjectEx("temp.chf");
data.ConnectionType = "TCP/IP";
data.PhoneNumber = host.IP;
data.AutoLoginName = host.Nombre.StartsWith("WS") ? "usrwksvc" : "admonadn";
data.AutoDomain = "dom" + actual.numec.PadLeft(4, '0');
data.WriteProtection = false;
data.WriteObject(null);
AWREM32.Document doc = new AWREM32.Document();
});
pcat.SetApartmentState(ApartmentState.STA);
pcat.Start();
pcat.Join();
CRemoteDataManagerClass, RemoteDataExClass и AWREM32.Document - это классы внутри сборок.
Итак, я получаю исключение в 5-й строке (data = (RemoteDataExClass)mng.RetrieveObjectEx("temp.chf", (short)2, null);
), в котором говорится следующее:
Невозможно преобразовать COM-объект типа winawsvr.CRemoteDataManagerClass в интерфейс типа winawsvr.IRemoteDataManager. Эта операция завершилась неудачно, поскольку вызов QueryInterface на COM-компоненте для интерфейса с IID «{82A1A806-8BA9-11CF-B95F-00A02412C812}» завершился неудачно из-за следующей ошибки: Interfaz несовместим (исключение из HRESULT: 0x80004002 (E_NOINTERFACE)).
Что я мог здесь упустить? Может что-то с тем, как прописаны COM компоненты? Раньше они были до того, как я даже попытался зарегистрировать их с помощью regasm.exe, только в CLSID были ключи LocalServer32 внутри них. Я считаю, что после запуска regasm.exe были созданы два: InprocHandler32 и InprocServer32. У меня одно и то же исключение до и после.
Я где-то читал, что мне нужно запустить вызывающий код в потоке, установленном в состояние квартиры STA. Так я и сделал. По-прежнему без изменений.
Еще я заметил, что когда я запустил ildasm.exe для сборки взаимодействия, в которой находится сбойный класс, я вижу в IRemoteDataManager строку: .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 38 32 41 31 41 38 30 36 2D 38 42 41 39 // ..$82A1A806-8BA9 ...
. IRemoteDataManager с TLB имеет идентификатор GUID 82A1A806-8BA9-11CF-B95F-00A02412C812
, который совпадает с идентификатором GUID, упомянутым в исключении. Первые два раздела этого GUID находятся в той строке, которую я упоминаю из ildasm (я полагаю, что остальное просто вырезано из-за проблем с отображением), так что и там все, кажется, хорошо.
Я пробовал использовать CRemoteDataManager (интерфейс, реализующий IRemoteDataManager) вместо CRemoteDataManagerClass, но сделка та же. В обоих случаях в исключении всегда упоминается CRemoteDataManagerClass. Из того, что я вижу в ildasm, CRemoteDataManagerClass реализует как CRemoteDataManager, так и IRemoteDataManager. Может быть, QueryInterface не работает на одном из двух, или что-то совсем другое.
Я не знаю. Я здесь явно повсюду.
Я также изучил ведение журнала взаимодействия, чтобы понять, почему именно QueryInterface дает сбой, но все, что я нашел, - это документация о том, как это сделать в .netcompactframework.