Форум: "Corba";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];
ВнизDCOM. Ошибка: Интерфейс не поддерживается. Найти похожие ветки
← →
Артем Кудлаекно (2005-10-18 12:59) [0]
library CalcSubscription;
uses
ComServ,
ComObj,
MyCalc_TLB in "MyCalc_TLB.pas",
Unit1 in "Unit1.pas" {Calc: CoClass};
exports
DllGetClassObject,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer;
{$R *.TLB}
{$R *.RES}
begin
end.unit MyCalc_TLB;
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface
uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants;
const
MyCalcMajorVersion = 1;
MyCalcMinorVersion = 0;
LIBID_MyCalc: TGUID = "{6C701D29-BF27-4B10-9139-B94F410CB5C2}";
IID_ICalc: TGUID = "{FD810922-1BDB-48D1-93D3-65E584854C6E}";
CLASS_Calc: TGUID = "{9D5C87A5-8BE2-40D8-B4C0-391D201F9B87}";
type
ICalc = interface;
Calc = ICalc;
ICalc = interface(IUnknown)
["{FD810922-1BDB-48D1-93D3-65E584854C6E}"]
function DoSomethind(as_text: OleVariant): HResult; stdcall;
end;
CoCalc = class
class function Create: ICalc;
class function CreateRemote(const MachineName: string): ICalc;
end;
implementation
uses ComObj;
class function CoCalc.Create: ICalc;
begin
Result := CreateComObject(CLASS_Calc) as ICalc;
end;
class function CoCalc.CreateRemote(const MachineName: string): ICalc;
begin
Result := CreateRemoteComObject(MachineName, CLASS_Calc) as ICalc;
end;
end.unit Unit1;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, ActiveX, Classes, ComObj, MyCalc_TLB, StdVcl, Dialogs;
type
TCalc = class(TTypedComObject, ICalc)
protected
function DoSomethind(as_text: OleVariant): HResult; stdcall;
{Declare ICalc methods here}
end;
implementation
uses ComServ;
function TCalc.DoSomethind(as_text: OleVariant): HResult;
begin
ShowMessage(as_text);
Result := S_OK;
end;
initialization
TTypedComObjectFactory.Create(ComServer, TCalc, Class_Calc,
ciMultiInstance, tmApartment);
end.
Код в приложении рабочий:procedure TForm1.Button2Click(Sender: TObject);
var Calc:ICalc;
begin
Calc := CoCalc.Create;
Calc.DoSomethind("Test");
end;
Код в приложении не рабочий:procedure TForm1.Button3Click(Sender: TObject);
var Calc:ICalc;
begin
Calc := CoCalc.CreateRemote("localhost");
Calc.DoSomethind("Remote is good!");
end;
CalcSubscription.dll скопировал в C:\Windows\System32.
Вызвал regsvr32 CalcSubscription.dll.
При вызове CreateRemote("localhost") в процессах появляется dllhost.
В dcomcnfg нашел свой GUID и дал всем все права.
Что я еще не сделал?
← →
isasa © (2005-10-18 13:26) [1]У DLL нет своего адресного пространства, поэтому она просто так DCOM не будет.
См. MSDN, ключевые слова Surrogate Sharing, DllSurrogate
← →
Артем Кудлаенко © (2005-10-18 14:19) [2]Получается, мне необходимо реализовать еще одну DLL: proxy/stub?
Я могу этого всего избежать, если сервер будет реализован в виде исполняемого файла?
← →
isasa © (2005-10-18 14:50) [3]По идее, да.
CLSCTX_REMOTE_SERVER = 16 (*.exe)
← →
Набережных С. © (2005-10-18 17:18) [4]>Артем Кудлаенко © (18.10.05 14:19) [2]
>Получается, мне необходимо реализовать еще одну DLL: proxy/stub?
Не обязательно. В данном случае
ICalc = interface(IUnknown)
["{FD810922-1BDB-48D1-93D3-65E584854C6E}"]
function DoSomethind(as_text: OleVariant): HResult; stdcall;
end;
в качестве proxy/stub может быть использован универсальный маршалер из oleaut32.dll, так как в методе интерфейса все параметры OleAutomation - совместимые.
>Я могу этого всего избежать, если сервер будет реализован в виде исполняемого файла?
Нет, proxy/stub необходимы. proxy/stub служат как раз для упаковки/распаковки параметров вызовов в вид, пригодный для передачи между процессами и машинами. Если клиент и сервер находятся в разных процессах, то пара proxy/stub необходима.
← →
isasa © (2005-10-18 17:43) [5]Не надо пугать человека.
Естественно маршаллинг(proxy/stub) будет.
Но писать самому его не придется.
← →
Набережных С. © (2005-10-18 18:35) [6]
> isasa © (18.10.05 17:43) [5]
> Не надо пугать человека.
Да, не придется - если будет использован универсальный маршалер из Oleaut32, как уже было сказано выше. Сам факт размещения сервера в exe-файле вовсе этого не гарантирует. В exe-сервере прекрасным образом могут располагаться объекты, реализующие не совместимые с оле интерфейсы, либо эти интерфейсы могут быть не помечены как OleAutomation, либо для них может не быть библиотеки типов - все эти варианты вполне допустимые, но только тогда потребуется иметь proxy/stub для каждого из реализованных в сервере интерфейсов, с которым предполагается работа клиентов.
Так что не надо путать человека.
← →
Набережных С. © (2005-10-18 18:43) [7]И еще, разумеется, не придется писать Proxy/Stub для тех интерфейсов, для которых proxy/stub уже кем-то написаны и имеются в системе, например большинство определенных в системе интерфейсов - ну это, думаю, вполне очевидно.
← →
Артем Кудлаенко © (2005-10-18 21:02) [8]Спасибо за разъяснения.
На данный момент меня proxy/stub пугает. И путаюсь немного тоже :)
Я сделал сервер в виде исполняемого файла. Все заработало.
1. Сейчас, когда все работает, используется универсальный маршалер?
2. Если я правильно понял, когда я буду использовать в параметрах методов типы не совместимые с OleAutomation, то мне прийдется писать свой proxy/stub?
3. Почему возникала ошибка "Interface not supported" пока я не зарегистрировал сервер на машине клиента?
4. Почему сервер выполнял недопустимую операцию, пока я не сменил учетную запись с которой запускается сервер с "Запускающего пользователя" на "Текущего пользователя"?
5. Когда я проверял эмпирическим путем какие права нужны для того, чтобы клиенты могли вызывать сервер, я запретил доступ всем. Теперь из dcomcnfg пропал мой сервер и я не могу вернуть все обратно. В реестре, естественно, не могу удалить все ветки с моим GUID`ом. Как можно вернуть все "на родину"?
← →
isasa © (2005-10-18 21:58) [9]Если без глубокой теории:
1. Да (в разных адресных пространствах)
2. Да. (поэтому этого лучше не делать). Если сильно приспичит передать, что-нибудь не OLE, например, record, пакуй ее в VarArray.
3. Proxy-часть маршалинга встроена в сервер.
4. Не знаю.
5. Попробуй вернуть права через Владелец (Кнопка Дополнительно).
Еще, мастер прототипом ставит(в D7) TAutoObject
TCalc = class(TAutoObject, ICalc) ????
← →
Артем Кудлаенко © (2005-10-18 22:14) [10]
> TCalc = class(TAutoObject, ICalc) ????
TCalc = class(TTypedComObject, ICalc)
И сейчас(после того как перевел сервер на исполняемый) в параметре метода тип не OleVariant, а WideString(Я все делал с помощью мастера и выбрал для метода тип BSTR)
← →
isasa © (2005-10-18 22:33) [11]WideString в *_TLB.pas - нормально.
См. View -> Type library -> тыкни на методе -> см. закладку Text
← →
Набережных С. © (2005-10-19 12:04) [12]
> isasa © (18.10.05 21:58) [9]
> 3. Proxy-часть маршалинга встроена в сервер.
Ну откуда такие фантазии?:( Я ж сказал - OleAut32...
> Артем Кудлаенко © (18.10.05 21:02) [8]
> 4. Почему сервер выполнял недопустимую операцию, пока я
> не сменил учетную запись с которой запускается сервер с
> "Запускающего пользователя" на "Текущего пользователя"?
Универсальному маршалеру на клиенте для правильной организации маршилинга вызовов требуется информация о типах параметров методов и о способе их передачи. Такая информация находится в библиотеке типов сервера и именно эта библиотека и необходима на клиенте. Когда ты на клиенте зарегистрировал сервер, то он автоматически зарегистрировал и свою библиотеку типов, поэтому и заработало. Хотя на клиенте регистрировать сервер нет необходимости, достаточно скопировать туда и зарегистрировать файл *.TLB.
> 4. Почему сервер выполнял недопустимую операцию, пока я
> не сменил учетную запись с которой запускается сервер с
> "Запускающего пользователя" на "Текущего пользователя"?
Вероятно, на компьютере сервера у клиента нет прав. Нужно дать права учетке клиента на сервере. Но лучше все-же установить запуск сервера от конкретной специально созданной учетной записи или от LocalSystem. Почему долго объяснять, а у меиня нет времени, поищи в инете есть.
> 5. Когда я проверял эмпирическим путем какие права нужны
> для того, чтобы клиенты могли вызывать сервер, я запретил
> доступ всем. Теперь из dcomcnfg пропал мой сервер и я не
> могу вернуть все обратно. В реестре, естественно, не могу
> удалить все ветки с моим GUID`ом. Как можно вернуть все
> "на родину"?
Попробуй войти в систему как админ, запусти regedt32, сделай себя владельцем и дай себе все права на эти ветки реестра. Должно помочь.
← →
Артем Кудлаенко © (2005-10-19 15:41) [13]Прочитал в справке, что массивы должны передавать через специальный тип называемый SafeArray. Я выбераю этот тип через окно мастера Type Library (SAFEARRAY(long))и у меня в параметр метода подставляется тип PSafeArray без указания типа(of long).
Как работать с массивами(двухмерными тоже)? Тип элементов я должен указать в скобках? На пример: SAFEARRAY(double)
Так же в справке написано(если я правльно понял), что в *_TLB модуле не отображается тип элементов.
← →
Набережных С. © (2005-10-19 17:50) [14]Дельфи умеет работать только с SafeArray of integer. И, кстати, в большинстве случаев удобнее иметь дело с OleVariant, чем напрямую с pSafeArray.
Для передачи массива записей существует несколько способов - через VarArrayCreate etc, через интерфейс-перечислитель, через объект, маршалируемый по значению. выбор зависит от условий задачи и от типов данных в записи.
ЗЫ Вопрос вышел за тему этой ветки, а в таких случаях принято создавать новые ветки.
Страницы: 1 вся ветка
Форум: "Corba";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.049 c