Форум: "Основная";
Текущий архив: 2002.11.07;
Скачать: [xml.tar.bz2];
Вниз---|Ветка была без названия|--- Найти похожие ветки
← →
Balu (2002-10-23 15:33) [0]Делаю в обычной программе:
...
DataBaseWRK := CreateComObject(CLASS_MyClass);
RegisterActiveObject(DataBaseWRK, CLASS_MyClass,
ACTIVEOBJECT_WEAK, FObjRegHandle);
CoLockObjectExternal(DataBaseWRK, TRUE, TRUE);
...
GetActiveObject(CLASS_MyClass, nil, Unknown);
if Unknown = nil
then MessageDlg("Нету ничего!", mtWarning, [mbOK], 0)
else MessageDlg("Подключились :-)", mtInformation, [mbOK], 0);
Все работает.
Пишу в Сервисе:
CoInitialize(nil);
DataBase := CreateComObject(CLASS_MyClass);
RegisterActiveObject(DataBase, CLASS_MyClass,
ACTIVEOBJECT_WEAK, FObjRegHandle);
CoLockObjectExternal(DataBase, TRUE, TRUE);
Application.Initialize;
Application.CreateForm(TSQL_Connection, SQL_Connection);
Application.Run;
Сервис стартует без проблем.
в программе пишу:
GetActiveObject(CLASS_MyClass, nil, Unknown);
if Unknown = nil
then MessageDlg("Нету ничего!", mtWarning, [mbOK], 0)
else MessageDlg("Подключились :-)", mtInformation, [mbOK], 0);
пишет Нету ничего!
Куда копать???
← →
Набережных С. (2002-10-23 19:14) [1]Создавать объект нужно в сервисном потоке. И если стартуешь сервис под LocalSystem, то просто так доступ не получишь.
И надо-бы проверять, чего функции возвращают.
← →
Balu (2002-10-23 19:46) [2]Пробовал создавать и в сервисном потоке: Результат тот же.
Коды возврата соответсвуют MSDN: все проходит нормально.
← →
Набережных С. (2002-10-23 20:04) [3]И GetActiveObject тоже? Поток вызывал CoInitialize? Какая потоковая модель? Очередь сообщений обрабатывается? В каком потоке регистрируется фабрика? Что с учетной записью? И почему CoLockObjectExternal, а не сразу ACTIVEOBJECT_STRONG?
← →
Balu (2002-10-23 20:41) [4]Прошу ногами не бить, а руками, ну что ж, надо же иногда по шапке за ламерство получать :(((((((
GetActiveObject возвращает Nil :(
CoInitialize вызывал.
> Какая потоковая модель? У кого? Если у сервиса, то незнаю :(, где это можно посмотреть.
> Очередь сообщений обрабатывается? Извиняюсь, но как это? :(
> В каком потоке регистрируется фабрика? ciMultiInstance
> Что с учетной записью? LocalSystem
> И почему CoLockObjectExternal, а не сразу ACTIVEOBJECT_STRONG? Если можно, то подробнее, плз.
← →
Balu (2002-10-23 20:46) [5]Блин, под вечер глючу :(
> Очередь сообщений обрабатывается? Конечно:
procedure TSQL_Connection.ServiceExecute(Sender: TService);
begin
while not Terminated do begin
ServiceThread.ProcessRequests(False);
Sleep(1000);
end;
end;
← →
Набережных С. (2002-10-23 21:53) [6]1)Для начала напиши в клиенте:
HRes: Cardinal;
HRes:=GetActiveObject(...
if HRes <> S_OK then ShowMessage(SysErrorMessage(HRes));
И обдумай то, что увидишь.
2)Я совсем не знаю дельфийской реализации сервисов и строка ServiceThread.ProcessRequests(False) мне ничего не говорит. Вызов Peek/GetMessage и DispatchMessage в ней производится?
Обработка необходима в случае STA.
И подозреваю, что Sleep(1000) здесь не совсем уместно.
3)Потоковая модель: тип апартамента, заявленный для объекта в вызове коструктора фабрики плюс тип апартамента потока, определяемая вызовом CoInitialize\CoInitializeEx. Должны соответствовать друг другу.
4)COM производит вызов CreateInstance фабрики в том апартаменте, из которого был вызван CoRegisterClassObject для этой фабрики. И если это STA, то в его потоке тоже должна обрабатываться очередь сообщений. Вообще в случае STA CoRegisterClassObject должен вызываться в том-же потоке, в котором будут создаваться объекты, если только реализация CreateInstance не предпримет специальных мер.
5)LocalSystem тебя по любому не пустит. Самое простое - выбрать учетку попроще.
6)RegisterActiveObject с флагом ACTIVEOBJECT_STRONG увеличивает на единицу счетчик внешних ссылок объекта. CoLockObjectExternal делает то-же самое. Лишний вызов.
Блин, под вечер глючу
А я вообще уже сплю:) Так что до завтра.
← →
Balu (2002-10-25 15:43) [7]> if HRes <> S_OK then ShowMessage(SysErrorMessage(HRes));
HRes = 2147746275
Операция недоступна
Что бы это значило? Извини незнаю :(
> 2)
procedure TServiceThread.ProcessRequests(WaitForMessage: Boolean);
const
ActionStr: array[1..5] of String = (SStop, SPause, SContinue, SInterrogate,
SShutdown);
var
msg: TMsg;
OldStatus: TCurrentStatus;
ErrorMsg: String;
ActionOK, Rslt: Boolean;
begin
while True do
begin
if Terminated and WaitForMessage then break;
if WaitForMessage then
Rslt := GetMessage(msg, 0, 0, 0)
else
Rslt := PeekMessage(msg, 0, 0, 0, PM_REMOVE);
if not Rslt then break;
if msg.hwnd = 0 then { Thread message }
begin
if msg.message = CM_SERVICE_CONTROL_CODE then
begin
OldStatus := FService.Status;
try
ActionOK := True;
case msg.wParam of
SERVICE_CONTROL_STOP: ActionOK := FService.DoStop;
SERVICE_CONTROL_PAUSE: ActionOK := FService.DoPause;
SERVICE_CONTROL_CONTINUE: ActionOK := FService.DoContinue;
SERVICE_CONTROL_SHUTDOWN: FService.DoShutDown;
SERVICE_CONTROL_INTERROGATE: FService.DoInterrogate;
else
ActionOK := FService.DoCustomControl(msg.wParam);
end;
if not ActionOK then
FService.Status := OldStatus;
except
on E: Exception do
begin
if msg.wParam <> SERVICE_CONTROL_SHUTDOWN then
FService.Status := OldStatus;
if msg.wParam in [1..5] then
ErrorMsg := Format(SServiceFailed, [ActionStr[msg.wParam], E.Message])
else
ErrorMsg := Format(SCustomError,[msg.wParam, E.Message]);
FService.LogMessage(ErrorMsg);
end;
end;
end else
DispatchMessage(msg);
end else
DispatchMessage(msg);
end;
end;
> 3)Потоковая модель:
STA
initialization
TAutoObjectFactory.Create(ComServer, TMyClass, CLASS_MyClass,
ciMultiInstance, tmApartment);
> 4) Извини, не понял. Если можно для ЧАЙНИКА (если есть желание)
> 5)LocalSystem тебя по любому не пустит
Попробовал свою учетную запись (я с правами сисадмин): результат тот же
Если есть в инете литература по данной тематике, прошу дать УРЛ. Боюсь со своими ЧАЙНИКОВСКИМИ вопросаму замучаю, может получится самому разобраться. Книжный рынок облазил весь ничего путного не нашел. В инете тоже :(((
← →
Набережных С. (2002-10-25 22:40) [8]Привет! А я вчера смотрю - молчишь, ну, думаю, разобрался:)
Ладно, начнем с конца.
По сервисам и безопасности относительно недавно вышла замечательная книга Рихтера и Кларка "Программирование серверных приложений для Win2000". Ну ты, я думаю, о ней уже не раз слышал. Очень, очень рекомендую, лучшее, что я видел.
С СОМ хуже. Все более-менее путное ориентировано на Си, еще меньше - переведено. Пожалуй лучшее -1998г.,Don Box, "Essential COM", , довольно неплоха так-же "СОМ+ технология" Оберга.
Некоторые главы из Бокса есть в MSDN. Слышал также, что она недавно выходила на русском. Если увидишь - хватай не раздумывая.
Ну и в MSDN много всего, правда сильно разбросано, но найти не трудно. А в сети все больше отрывочно, по узким темам.
Теперь по учетке. Если ты явно не вызываешь CoInitializeSecurity, то СОМ использует дескриптор безопасности процесса, в данном случае сервиса. А это означает, что при LocalSystem без дополнительных настроек безопасности никто к нему не сможет подключиться. Натраивать можно и программно, и это дает исключительную гибкость, но тема настолько велика и сложна, что явно не подходит для форума. Очень рекомдую названную книгу Рихтера. Однако под своей учеткой ты доступ получишь и так, поэтому проблема, видимо в другом.
Я тут мельком посмотрел, как реализуются сервисы в дельфи. Получается, главный поток приложения создает специальный поток, который уже стартует сервисы, а главный продолжает работать, обрабатывая очередь(если я правильно понял при беглом знакомстве) Но в этом случае твой вариант от 23.10.02 15:33 вроде должен работать, а вот при создании объекта в сервиcном потоке - нет, потому как в этом случае ты получишь интерфейс прокси, а не объекта. Приведенный код ошибки собычно означает, что искомый объект в ROT не зарегистрирован. Надо бы точно убедиться, что объект создается и CoRegister... возвращает S_OK. А вообще мне тут трудно строить предположения, обычно главный поток приложения ждет возврата из StartServiceCtrlDispatcher, а все делается в сервисных потоках: создается фабрика или просто класс-объект, явно регистрируется, и дальше в зависимости от задачи. Но дельфийский сервис организован иначе...
Еще вот что. Для COM-сервера в сервисе в AppID реестра должен быть параметр LocalService, указывающий на твой сервис. Проверь, вряд ли дельфи его добавит.
Если хочешь, скинь проект(без исходников!)мне на ящик, в воскресенье будет время, помотрю: RandomPasserBy@nm.ru.
P.S. А по 4) очень уж долго объяснять, раз ты так не понял, целая статья получится. Лучше почитай, будут поконкретней вопросы - давай. Постарайся представить все это в динамике - что в какой последовательности делается, когда и как вызывается.
Погоняй под отладчиком, используй логи - я так разбирался:)
← →
Balu (2002-10-26 17:40) [9]Спасибо за предложенную помощь, но сейчас сырцов нет, пишу из дома.
За указание "светлого" пути, отдельное спасибо.
Литературу попробую найти, так что в районе недели, наверно появляться не буду, попытаюсь разобраться. А потом .... что будет потом посмотрим.
СПАСИБО.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.11.07;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.008 c