InvalidCastException, сбой вызова QueryInterface на COM-компоненте

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


person rhyek    schedule 04.08.2010    source источник


Ответы (1)


Мне кажется, что

data = (RemoteDataExClass)mng.RetrieveObjectEx("temp.chf", (short)2, null);

может возникнуть проблема. Я считаю, что (RemoteDataExClass) пытается привести mng к его типу до вызова .RetrieveObjectEx. Это может привести к вашей ошибке. Другой вариант может заключаться в том, что одному из объектов класса не нравится оператор New. Я заметил в различных ситуациях, когда эти библиотеки предлагают новый оператор, который выдает ошибки, но есть и другие классы с функцией сортировки Create. Используя их, можно получить класс Created, необходимый для получения.

person Jimmie Clark    schedule 07.09.2010