Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ERROR "Сбой при удалённом вызове процедуры"


LeS ©   (2002-07-31 17:46:00) 

Уважаемые мастера, подскажите.
Создал приложение, добавил в него ком объект, в интерфейсе которого один метод. Подготовил клиента, который создаёт коинтерфейс.CreateRemote('SERVER') и обращается к этому методу. Работает на одной машине, а вот если унести клиент на другую, то появляется синий экран:( с просьбой нажать ctrlaltdel:). На нем сообщение: ИМЯ ФАЙЛА: VREDIR(06)+00006054 ошибка 0E:0028:C02D272Q. Если игнорировать просьбу и нажать на любую клавишу, винда показывает ShowMessage("Сбой при удалённом вызове процедуры"). Если же повторно вызвать метод, то появляется сообщение "Сервер RPC недоступен").
ОС на клиенте - Винда миллениум
ОС на сервере - В2000 . Все сервисы, которые, как мне показалось, связанны с лок сетью (в том числе "удалённыый вызов процедур",Локатор удаленного вызова процедур (RPC) и др) - запущены, папочка, в которой лежит серверное приложение - расшарена с полным доступом для всех .
Подскажите пожалуйста, как быть...

Заранее, спасибо.


LeS   (2002-08-01 12:46:00) [1]

Всё, до сервака я достучался.
Просто чтото напутал в dcomcnfg.exe. Проверил, запустид - работает.

Спасибо большое. Приятно иметь дело с А. Н. Оним. Всего хорошего.    


А. Н. Оним   (2002-08-01 12:32:00) [2]

Есть несколько вопросов:
*  Какая у тебя сеть: если без контроллера (например, две машины по нульмодемному), то права "ВСЕ" для неопознанного сервером клиентского пользователя ничего на самом деле не дают.
*  В какой момент вылетает ошибка? На CreateRemoteComObject? Или при вызове метода (если да, то какого?).
*  Запущен ли сервер уже в тот момент или он только запускается?
 


LeS   (2002-08-01 12:26:00) [3]

Огромное спасибо за подробное описание, А. Н. Оним.

Не работает. Интересно получается... Я программирую в делфи 6, похоже он сам зарегистрировал мой сервер, т.к. без копания в реестре я нашел его в списке dcomcnfg.exe, а на этапе раздачи прав не стал мудрить и поставил на запуск, доступ пользователя "ВСЕ". Теперь ошибки нет, зато есть другая.:) Клиент долго думает, потом показывает "Ошибка при выполнении приложения-сервера". Сервер же пишет - "Исключение неизвестное программное исключение (0x0eedfade) в приложении по адресу XXXXXX". Вот такие вот дела, начинаю подумывать, что может  я чтото сам неправильно напрограммил, хотя, повторяюсь, на одной машине работает.
Если ошибка относится к стандартным, прошу просветить меня, буду очень благодарен.

Спасибо.


А. Н. Оним     (2002-08-01 11:45:00) [4]

 Пардон, погоречился, для программируемой политики безопасности следует использовать интерфейс IAccessControl, но в стандартных pas модулях с Дельфи его нет. Чтобы получить его описание, можешь сгенерить в MSVC пустую болванку сервера и в IDL воткнуть строчку - include "iaccess.idl". Не беда, что сервер получиться пустой после компиляции - он тебе не нужен. Нужна его TypeLIB. Импортируй её в Delphi и получишь отображение интерфейса IAccessControl (и ещё кучу всего, включая структуры типа DACL, SACL, и т.д.) на язык Pascal. Импорт TypeLib в Delphi: Project/Import Type Library. Найди её сам руками. Реализуй IAccessControl и воткни его в код инициализации сервера (ещё до регистрации фабрики класса) примерно так:

 CoInitializeEx (nil, COINIT_MULTITHREADED);
 IUnk := nil;
 IUnk := AccessControlObjectFactory.CreateComObject(nil);
 IUnk._AddRef();
 hRes := CoInitializeSecurity(pointer(IUnk), -1, nil, nil, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IDENTIFY, nil,
         EOAC_ACCESS_CONTROL, nil);

 AccessControlObjectFactory - это фабрика кокласса, что реализует этот самый IaccessControl. Тебе придётся добавить ещё один кокласс в проект. Теперь SCM будет каждый раз дёргать тебя за метод IsAccessAllowed этого интерфейса, выдавая пользователя с портахами, а ты уж решай, дать ему доступ или нет.
Но программируемая политика безопасности не обязательна.
-------------------------------
Чуть не забыл. Существует деликатный вопрос о том, как сервер запускается с другой машины. Если он уже запущен на сервере из командной строки, то ясное дело, он несёт маркер пользователя, который зарегестрирован сейчас на сервере и обладает его правами (правами доступка к файлам, перефирийным устройствам, обектам ядра и т.д.). А что если пользователь его не запускал, а запускает кто-то другой? Кем должен стать сервер? Пользователем сервера (получить его маркер) или пользователем клиента? Это очень важно, так как это вопрос безопасности в целом. Если на сервере Админ, а запускает с другой машины ограниченный в правах User, а сервер становиться админом - то через него пользователь может действовать с правами админа и стоит только надеяться, что в его коклассе нет метода типа "отформатировать жёсткий диск".
 Все эти вопросы решать тебе, а dcomcnfg позволяет воплотить решение в жизнь на вкладке Identify. По умолчанию там стоит launching user - то есть сервер при запуске со стороны станет запускающим пользователем и не даст ему никаких дополнительных прав. Всё бы ничего, но если на сервере кто-то другой (как чаще всего и бывает), а не пользователь, инициирующий запуск, то получается забавная ситуация - сервер не имеет средств для взаимодействия с рабочим столом. Он не может ничего на нём нарисовать, создать на нём форму, он молчалив и глух, а пользователь на сервере даже не может его снять через TaskManager. Почему? Дело в том, что в тот момент, когда сервер станет другим пользователем сети (вополиться в него), то он получит свой рабочий стол (и этот рабочий стол совсем не тот, что у текущего пользователя), а у пользователя сервера не хватает прав. Если у тебя какой-нибудь сервер автоматизации с формой, то в момент "подъёма" вылетит какая-то устрашающая ошибка и сервер тут же грохнется.
 Поэтому переключи вкладку на Interactive User. Но только здесь надо быть очень аккуратным с правами и неплохо бы реализовать ту самую программную политику безопасности. Ведь теперь сервер будет при запуске тем, кто сидит на машине.
 Всё это также описано в книге Рихтера.
Про настройку машин с контроллером и без контроллера домена я уже писал где-то в разделе DCOM.



 


А. Н. Оним   (2002-08-01 11:18:00) [5]

 Привет, прежде всего, твой сервер должен регистрировать в реестре свой AppID. AppID - это уникальный идентификатор твоего сервера (не кокласса сервера, а именно сервера целиком). Служит, как правило, для занесения информации о тех, кому положен доступ к нему, а кому нет. В отличие от progID, он не дружелюбный пользователю, а самый - самый типичный TGUID. Далеко не каждый сервер его для себя создаёт при регистрации. Все AppID в твоей системе лежат в:
 HKEY_CLASSES_ROOT\AppID\
Посмотри - их не так уж и много. Каждая из вкладок может содержать две записи LaunchPermission и AccessPermission. Если очень коротко - то в них бинарный Security Descriptor со списком DACL. DACL - это разграничительный список доступа. В нём перечислены User'а, которые могут или не могут запускать твой сервер. В LaunchPermission - списки тех, кому разрешено запускать твой сервер с удалённой машины, в AccessPermission - список тех, кому разрешено обращаться. Очень подробно этот вопрос рассмотрен в толстой синей книге Джефрри Рихтера "Разработка серверных приложений для Windows 2000". Твой сервер должен зарегестрировать свой AppID, перечислить тех - кому положено его запускать, связать свой CLSID со своим AppID и всё готово. Как это сделать:
 Если ты пишешь в Delphi, то код для занесения AppID для твоего сервера дельфёфский Wizard не сгенерит. (MSVC'шный генерит). Проблема решается, например, так:
 AppID - тот же GUID и ты должен придумать его для себя сам. GUID сочинит для тебя также утилита GUIDGEN.EXE, но можешь и сам его придумать (можно также посмотреть в MSDN о программном способе генерации структур типа GUID).
 Код для регистрации в Delphi может быть примерно такой:
unit ...
var
 lpszMyCLSID, lpszMyAppID: string;

initialization
 lpszMyCLSID := '{AFBA5900-38E1-436B-8EE8-70C6D07214EB}';
 lpszMyAppID := '{3AA83FD2-8274-4606-90F5-5EE2781FBBC9}';
 CreateRegKey('APPID\' + lpszMyAppID, '', 'дружеское имя сервера');
 CreateRegKey('CLSID\' + lpszMyCLSID, 'AppID', lpszMyAppID);

 Вместо AppID воткни свой AppID, а вместо CLSID - свой CLSID, посмотри его в TypeLIB'е своего проекта для кокласса. Теперь сервер будет оставлять о себе необходимые записи в реестре.

Настроить список лиц, кому позволен доступ к серверу можно при помощи утилиты dcomcnfg.exe на машине сервера. При запуске утилиты появиться окошко - и о чудо, твоё 'дружеское имя сервера' будет в нём. dcomcnfg просто просканировал влкадку APPID твоего реестра. Теперь дважды щёлкни на нём и настрой доступ и запуск как пользовательский. Не забудь ещё вот о чём.
Если ты не дашь прав на запуск, то клиент может только надеяться, что сервер уже кем то запущен. Если же у клиента нет прав на доступ (Access), то у него вообще никогда не получиться добраться до сервака. Сервер может дополнительно реализовывать программиоумемую политику безопасности при помощи интерфейса IClientSecurity и разграничивать к себе доступ по любой логике. Но это уже отдельная история.

Удачи.





LeS   (2002-08-01 10:07:00) [6]

Спасибо А. Н. Оним   .
Поставил клиента на винду98. Ошибка №3. Но могу понять, почему. Не силён администрировании, но и не последний чел в этом, все политики, все службы (кажись) - разрешены и включены. Кто нибудь знает конкретно, как разрешить доступ, что нужно вкл, а что выкл?..
А что делать на разных платформах?


А. Н. Оним   (2002-07-31 18:29:00) [7]

Да - а - а. Затрудняюсь что-либо и сказать. Но я встречался с 3-емя типами ошибок и огромной кучей баек своих друзей: Ошибки перечисляю по первичности их возникновения:
1. [RPC сервер не доступен] Чаще всего возникает тогда, когда целевая машина действительно не доступна по сетке. Но однажды у меня такое было в локалке, когда одна машина действительно из непонятных причин была видна только по своему IP'шнику. Попробуй указать его, вдруг поможет?
2. [CLSID не зарегестрирован] - CLSID отсутствует на целевой машине. Просто не разегестрирован сервер. Может появиться только тогда, когда ошибка "1" устранена
3. [Access Denied] - политика безопасности должным образом не настроена. Может появиться только в том случае, когда ошибки "1" и "2" ты счастливо избежал.
 А друзья рассказывали про "несовместимости DCOM на различных вариантах Windows платформ", про "неразворачиваемые сервисы" и т.д. Так что могу посоветовать развернуть для начала на одинаковых платформах. Желательно, Win2000 или WinNT.


Наверх

Титульная страница Поиск, карта сайта Написать письмо