Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.02.18;
Скачать: CL | DM;

Вниз

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 вся ветка

Текущий архив: 2007.02.18;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.072 c
10-1129215610
QwertyMan
2005-10-13 19:00
2007.02.18
Написал ActiveFormX, как сделать регистрацию через Бровзер


2-1169979892
w666w
2007-01-28 13:24
2007.02.18
Иероглифы в TMemo и TEdit


15-1169990206
Eraser
2007-01-28 16:16
2007.02.18
Название DLL и копирайт


15-1169306037
Mr. D.
2007-01-20 18:13
2007.02.18
Показ "панели задач" при работе TMediaPlayer


2-1170276381
Wlad_M
2007-01-31 23:46
2007.02.18
Как вписать недостающий класс в экзешник