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

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

Как преобразовать OleVariant в IAdsMembers? Пытаюсь так:


EgorovAlex ©   (2005-11-06 12:00:00) 


var
 Group: IADsGroup;
 Members: IAdsMembers;
 varMembers: OleVariant;
...
ADsGetObject('LDAP://' + AdsPath, IADsGroup, Group);
varMembers := Group.GetEx('MemberOf');
Members := IDispatch(varMembers) as IAdsMembers;

так вот на последней строке ругается:
Could not convert variant of type(Array Variant) into type (Dispatch).

Как же мне его туда загнать?


EgorovAlex   (2005-11-08 14:23:00) [1]

To Набережных С.
Спасибо, действительно было не совсем верное описание AdsGetObject
Теперь всё работает как надо.


Набережных С.   (2005-11-08 13:35:00) [2]


> процедура VariantClear() принимает параметром отнюдь не
> OleVariant-значение , а TVarData-значение !

Это одно и то же.

> EgorovAlex ©

У тебя портится стек, скорее всего из-за неправильных деклараций. Обрати внимание, чтобы все параметры интерфейсных типов были объявлены со спецификаторами const, var или out. Т.е. недопустимо такое:
function SomeFunc(Value: IInterface)
Должно быть как-то так:
(const Value: IInterface), (var Value: IInterface), (out Value: IInterface).

То же касаетсе параметров типа TGUID.

Мне нужно уходить, если что - вечером, если получится.


Digitman   (2005-11-08 13:02:00) [3]


> VariantClear(varGroup);


это что за беда ?

процедура VariantClear() принимает параметром отнюдь не OleVariant-значение , а TVarData-значение !


Набережных С.   (2005-11-08 12:51:00) [4]

Откуда берешь декларации? В общем, покажи декларации всех использованных импортных функций и интерфейсов.


EgorovAlex   (2005-11-08 12:39:00) [5]

Я понимаю, но во время трассировки моей функции всё нормально работает и показывает, а вот после выхода из неё переменные C и Self уже испорчены.


Digitman   (2005-11-08 12:25:00) [6]

встроенный отладчик Борландом был писан не для Пушкина, а для тебя)


EgorovAlex   (2005-11-08 11:56:00) [7]

Написал такую процедуру получения всех глобальных вложенных групп для пользователя в домене, она работает правильно:

function GetAllGroupsForUser(DomainName, UserName: WideString; Groups: TStrings): Boolean;
var
 varGroups: TStringList;

 procedure GetGroupsForGroup(AdsPath, GroupName: WideString);
 var
   Connection, Command, Res: Variant;
   Group: IADsGroup;
   varMembers: OleVariant;
   varGroup, varType: WideString;
   I, N, L: Integer;
 begin
   if (AdsPath = '') then
   begin
     Connection := CreateOleObject('ADODB.Connection');
     Command := CreateOleObject('ADODB.Command');
     try
       Connection.Provider := 'ADsDSOObject';
       Connection.Open('Active Directory Provider');

       Command.ActiveConnection := Connection;
       Command.Properties('Page Size') := 1000;
       Command.Properties('Searchscope') := ADS_SCOPE_SUBTREE;
       Command.CommandText := 'SELECT distinguishedName FROM ''LDAP://' + DomainName +
                              ''' WHERE objectCategory=''group'' AND sAMAccountName=''' + GroupName + '''';
       try
         Res := Command.Execute;
         if not Res.EOF then
           AdsPath := Res.Fields[0].Value;
       except
       end;
       Res := NULL;
     finally
       Command := NULL;
       Connection.Close;
       Connection := NULL;
     end;
   end;
   if (AdsPath <> '') then
   begin
     ADsGetObject('LDAP://' + AdsPath, IADsGroup, Group);
     try
       varMembers := Group.GetEx('MemberOf');
       for I := 0 to VarArrayHighBound(varMembers, 1) do
       begin
         varGroup := varMembers[I];
         N := Pos('CN=', varGroup);
         Delete(varGroup, 1, N + 2);
         varType := varGroup;
         N := Pos(',', varGroup);
         L := Length(varGroup);
         Delete(varGroup, N, L);
         if (Groups.IndexOf(varGroup) = -1) then
         begin
           Groups.Add(varGroup);
           N := Pos('CN=', varType);
           if (N > 0) then
           begin
             Delete(varType, 1, N + 2);
             N := Pos(',', varType);
             Delete(varType, N, L);
             if not WideSameText(varType, 'Builtin') then
               varGroups.Add(varMembers[I]);
           end;
         end;
       end;
     except
     end;
   end;
 end;

var
 Enum: IEnumVariant;
 User: IADsUser;
 Members: IAdsMembers;
 Group: IAdsGroup;
 varGroup: OleVariant;
 Temp: LongWord;
begin
 Result := False;
 varGroups := TStringList.Create;
 try
   if WideSameText(DomainName, LocalComputer) then
   begin
   end
   else
   try
     ADsGetObject('WinNT://' + DomainName + '/' + UserName, IADsUser, User);
     Members := User.Groups;
     Enum := Members._NewEnum as IEnumVariant;
     if Assigned(Enum) then
       while (Enum.Next(1, varGroup, Temp) = S_OK) do
       begin
         Group := IDispatch(varGroup) as IAdsGroup;
         Groups.Add(Group.Name);
         GetGroupsForGroup('', Group.Name);
         VariantClear(varGroup);
       end;
   except
   end;

   while (varGroups.Count > 0) do
   begin
     GetGroupsForGroup(varGroups[0], '');
     varGroups.Delete(0);
   end;
 finally
   varGroups.Free;
 end;
end;

procedure TForm1.btnUserAdsPathClick(Sender: TObject);
var
 C: Cardinal;
begin
 memGroups.Lines.Clear;
 C := GetTickCount;
 GetAllGroupsForUser(edtDomain.Text, edtUser.Text, memGroups.Lines);
 Form1.Caption := IntToStr(GetTickCount - C);
//  Caption := Form1.Caption;
end;


Так вот самое интересное и непонятное - после её вызова в btnUserAdsPathClick теряются значения переменной С и Self, т.е. если расскоментировать последнюю строчку, то вылетает исключение и в переменной C совсем не то значение, которое было перед вызовом.
Как такое может быть и где ковыряться для исправления? (Delphi 7)


EgorovAlex   (2005-11-06 15:41:00) [8]

Спасибо, помогло. В элементах этого массива OleStr находятся.


Набережных С.   (2005-11-06 15:32:00) [9]


> EgorovAlex ©   (06.11.05 14:57) [2]

Ну так и чего же тогда искать в нем интерфейс, если приходит массив?
8204 - array of Variant (см. Variant type codes в System.pas). Вот и смотри, что там в каждом из элементов этого массива, типа
for n:=VarArrayLowBound(varMembers, 1) to VarArrayHighBound(varMembers, 1) do
 ...varMembers[n]....

И DimCount тоже проверь.


EgorovAlex   (2005-11-06 14:57:00) [10]

К сожалению не работает :(

Вот оригинальный код на vbs, который работает:


Set objGroup = GetObject("LDAP://" & AdsPath)

arrMembersOf = objGroup.GetEx("MemberOf")

WScript.Echo "MembersOf:"
For Each strMemberOf in arrMembersOf
   WScript.Echo strMemberOf
Next


Т.е. это заведомо правильная конструкция, а у меня в отладчике для varMembers Delphi пишет, что это "Variant array of Variant" и тип TVarData(varMembers).VType = 8204


Набережных С.   (2005-11-06 12:38:00) [11]

IDispatch(Members):=varMembers;
Members:=Members as IAdsMembers;

или

if TVarData(varMembers).VType = varDispatch then
 Members:= IDispatch(TVarData(varMembers).VDispatch) as IAdsMembers;

Или, более строго, объявить дополнительную переменную типа Idispatch и передать через нее.


Наверх

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