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