InvalidCastException, сбой вызова QueryInterface для компонента COM - PullRequest
4 голосов
/ 04 августа 2010

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

1 Ответ

2 голосов
/ 07 сентября 2010

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

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

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

...