Я пытаюсь использовать 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.