![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
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.