Вопрос, поставленный пользователем, заключается в передаче интерфейса IVApplication из дополнения Visio в другой COM-сервер. При этом возникает ошибка OLE, указывающая на проблему при маршалинге. Рассмотрим, как можно решить данную задачу, используя возможности Delphi и Object Pascal.
Описание проблемы
Пользователь пытается передать интерфейс IVApplication из дополнения для Visio в другой COM-сервер. Для этого используется маршалинг через поток IStream. Однако, при попытке размаршалить интерфейс на стороне COM-сервера, возникает ошибка, и процесс не может быть завершен.
Пример кода из дополнения Visio
var
IStrm: IStream;
hres: HResult;
rhglobal: HGLOBAL;
VisioAppl: IVApplication;
begin
hres := CreateStreamOnHGlobal(0, TRUE, IStrm);
if Succeeded(hres) then
begin
hres := CoMarshalInterface(IStrm, IID_IVApplication, VisioAppl,
MSHCTX_LOCAL, 0,
MSHLFLAGS_NORMAL);
if Succeeded(hres) then
begin
hres := GetHGlobalFromStream(IStrm, rhglobal);
if Succeeded(hres) then
Result := rhglobal;
IStrm := nil;
end;
end;
end;
Пример кода COM-сервера
procedure MyCOMServer(AHGlobal: HGlobal);
var
VisioAppl: Visio_TLB.IVApplication;
iStrm: IStream;
hres: HResult;
begin
iStrm := Nil;
VisioAppl:= nil;
hres := CreateStreamOnHGlobal(AHGlobal, FALSE, iStrm);
if (SUCCEEDED(hres)) then
begin
hres := CoUnmarshalInterface(iStrm, Visio_TLB.IVApplication, VisioAppl);
iStrm := nil;
ShowMessage('Result:' + BoolToStr(SUCCEEDED(hres))); // <-- результат 0
ShowMessage(VisioAppl.ProductName); // <-- ошибка
end;
end;
Альтернативное решение
В качестве альтернативного решения предлагается передать интерфейс напрямую, без использования маршалинга через поток. Это можно сделать, определив метод в COM-сервере, который принимает параметр в виде OleVariant или IDispatch*, и затем на стороне сервера привести его к интерфейсу IVApplication.
Пример кода для дополнения Visio
procedure SendAppToComServer(aIntf: Visio_TLB.IVApplication);
begin
MyComServer.PassVisioApp(aIntf);
end;
Пример кода для COM-сервера
procedure TMyComServer.PassVisioApp(VisioApp: OleVariant);
var
VisioAppIntf: Visio_TLB.IVApplication;
begin
VisioAppIntf := VisioApp as Visio_TLB.IVApplication;
ShowMessage(VisioAppIntf.ProductName);
end;
Подтвержденное решение
При использовании OleVariant для передачи интерфейса, необходимо обратить внимание на приведение типа на стороне COM-сервера. В случае с Visio, использование IDispatch вместо OleVariant может быть более предпочтительным, так как это позволяет корректно работать с интерфейсами COM.
Выводы
Передача интерфейсов в COM-серверы требует особого внимания к деталям, особенно при использовании маршалинга. В случае возникновения ошибок, важно тщательно анализировать значения HResult, чтобы понять причину проблемы. Альтернативный подход, предложенный в решении, позволяет избежать сложностей с маршалингом и упрощает взаимодействие между компонентами.
Пользователь сталкивается с проблемой передачи интерфейса `IVApplication` из дополнения для Microsoft Visio в COM-сервер с использованием Delphi, и проблема заключается в ошибках OLE при маршалинге через поток `IStream`.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.