ADSI и Delphi: Правильное закрытие соединения при использовании ADsOpenObject
При работе с Active Directory Service Interfaces (ADSI) в Delphi одним из распространенных вопросов является правильное закрытие соединения после его использования. В этой статье мы рассмотрим, как решить проблему неправильного закрытия соединения, которая может возникнуть при использовании функции ADsOpenObject.
Описание проблемы
Рассмотрим следующий код, в котором демонстрируется попытка получить путь группы Windows по имени пользователя и паролю:
procedure ShowADSPath(UserName, Password: widestring);
var
Group: IADs;
begin
try
OleCheck(ADsOpenObject('WinNT://Server/Group1',
UserName,
Password, ADS_SECURE_AUTHENTICATION, IADs, Group));
if (Group <> nil) and (Group.Class_ = 'Group') then
ShowMessage(Group.ADsPath);
Group.release;
Group := nil;
except
ShowMessage('NOT ACCESSDE');
end;
end;
Проблема заключается в том, что после первого успешного или неудачного вызова этой функции, последующие вызовы могут возвращать неверные результаты, независимо от правильности введенных имени пользователя и пароля. Это происходит из-за неправильного закрытия соединения с сервером.
Подтвержденный ответ
После тщательного исследования был найден Decision 218497 в базе знаний Microsoft, который описывает подобную проблему с API функцией ADsOpenObject. Функция открывает соединение с сервером, используя переданные ей учетные данные, но не закрывает его после завершения работы. Попытки закрыть соединение не приводят к ожидаемым результатам, так как оно не закрывается в текущей сессии.
Чтобы решить проблему, можно использовать другой API для проверки существования объекта перед открытием соединения. Вот пример функции, которая решает проблему:
procedure ShowADSPath(UserName, Password: widestring);
function CheckObject(APath: String): IDispatch;
var
Moniker: IMoniker;
Eaten: Integer;
BindContext: IBindCtx;
Dispatch: IDispatch;
begin
Result := nil;
OleCheck(CreateBindCtx(0, BindContext));
OleCheck(MkParseDisplayName(BindContext, PWideChar(WideString(APath)),
Eaten, Moniker));
OleCheck(Moniker.BindToObject(BindContext, nil, IDispatch, Dispatch));
Result := Dispatch;
end;
var
Group: IADs;
begin
try
if CheckObject('WinNT://Server/Group1,group') <> nil then
begin
OleCheck(ADsOpenObject('WinNT://Server/Group1,group',
UserName,
Password, ADS_SECURE_AUTHENTICATION, IADs, Group));
if (Group <> nil) and (Group.Class_ = 'Group') then
begin
ShowMessage(Group.ADsPath);
Group.release;
Group := nil;
end;
end;
except
ShowMessage('NOT ACCESSDE');
end;
end;
В этой функции CheckObject сначала проверяет existence объекта, а затем, если объект существует, открывает соединение с сервером и получает путь группы. Это гарантирует правильное закрытие соединения после его использования.
Альтернативный ответ
Хотя решение, описанное выше, является наиболее надежным способом решить проблему, существует альтернативный подход, заключающийся в использовании объекта IADsContainer для получения членов группы. Этот подход не требует закрытия соединения явно, так как объект IADsContainer автоматически закрывается после использования. Вот пример кода, демонстрирующего этот подход:
procedure ShowGroupMembers(UserName, Password: widestring; GroupName: string);
var
Group: IADsContainer;
begin
try
OleCheck(ADsOpenObject('WinNT://Server/' + GroupName,
UserName,
Password, ADS_SECURE_AUTHENTICATION, IADsContainer, Group));
if Group <> nil then
begin
var
Member: IADs;
for Member in Group do
begin
if Member.Class_ = 'user' then
ShowMessage(Member.ADsPath);
Member.release;
end;
Group.release;
end;
except
ShowMessage('NOT ACCESSDE');
end;
end;
В этом примере функция ShowGroupMembers открывает объект IADsContainer для указанной группы и перебирает всех членов группы, отображая путь каждого члена пользователя. После завершения работы с объектом IADsContainer он автоматически закрывается, что гарантирует правильное закрытие соединения.
Заключение
При работе с ADSI в Delphi важно правильно закрывать соединение после его использования. В противном случае могут возникнуть проблемы с получением неверных результатов при повторных вызовах функций, работающих с ADSI. Использование функции CheckObject для проверки existence объекта перед открытием соединения или использование объекта IADsContainer для получения членов группы являются надежными способами решить проблему неправильного закрытия соединения.
В статье рассматривается проблема правильного закрытия соединения при использовании ADsOpenObject в Delphi для работы с Active Directory Service Interfaces (ADSI). При неправильном закрытии соединения могут возникать проблемы с получением неверных результ
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.