Чтение флага SECURITY_ENABLED группы в Active Directory

Я пытаюсь прочитать флаг SECURITY_ENABLED свойства groupType группы . Проблема в том, что значение, которое я получаю, используя

DirectoryEntry entry...
entry.Properties["groupType"].Value;

представляет собой int32, диапазон которого составляет -2 147 483 647 до 2 147 483 648 (или от -0x7FFFFFFF до 0x80000000)

quickWatch

Таким образом, в любое время, когда установлен GROUP_TYPE_SECURITY_ENABLED и любой другой флаг арбитража, числовое значение превышает диапазон int32, и происходит переполнение.

groupTypeScreen

Кто-нибудь знает, как избежать этого переполнения, чтобы прочитать правильное значение?


person wodzu    schedule 15.05.2013    source источник
comment
должен ли флаг быть целым числом 0x80000000, хорошо вписывающимся в единицу.   -  person urbanlemur    schedule 15.05.2013
comment
По умолчанию Int32 подписан. Вы можете использовать UInt32 ??   -  person fourpastmidnight    schedule 15.05.2013
comment
Entry.Properties[groupType].Value возвращает -2147483646. Когда я пытаюсь привести его к uint, я получаю InvalidCastException   -  person wodzu    schedule 15.05.2013


Ответы (2)


Я думаю, вам нужно использовать UInt32 как тип вашего перечисления GroupType следующим образом:

[Flags]
public enum GroupType : uint
{
    BUILTIN_LOCAL_GROUP = 0x00000001,
    ACCOUNT_GROUP       = 0x00000002,
    RESOURCE_GROUP      = 0x00000004,
    UNIVERSAL_GROUP     = 0x00000008,
    APP_BASIC_GROUP     = 0x00000010,
    APP_QUERY_GROUP     = 0x00000020,
    SECURITY_ENABLED    = 0x80000000
}

Дайте мне знать, если это решит вашу проблему.

EDIT: Хорошо, я не был уверен, был ли Entry созданным вами объектом или частью API Active Directory. Сказав это, я быстро создал следующие переменные в проекте, над которым сейчас работаю, и скомпилировал следующим образом:

// I only made it static so I could get my compiler to compile this in something I'm currently
// working on. It's not necessary for it to be static.
static int SECURITY_ENABLED = 0x80000000;

int newValue = SECURITY_ENABLED | 1;

Я не получил никаких ошибок времени компиляции. На самом деле, повторно взглянув на значение 0x80000000, оно находится в диапазоне Int32.

Повторно глядя на ваш код выше, в какой именно строке вы получаете сообщение об ошибке? Я вижу этот подозрительный код:

if (groupTypes.Count == 1)
{
    var  firstFlag = (int) groupTypes[0];

    // What is this checking, exactly?
    // Is this where the error is occurring?
    var longFlag = -(((long) flag) - firstFlag);

    if ((longFlag == 0x80000000)) // Extra parentheses here...just a formatting thing
        groupTypes.Add(GroupType.SECURITY_ENABLED);
}

Возможно, этот код можно упростить?

public List<GroupType> GetGroupType()
{
    var groupTypes = new List<GroupType>();
    var flag = (GroupType) this.Entry.Properties["groupType"].Value;

    if (flag & GroupType.ACCOUNT_GROUP > 0)
        groupTypes.Add(GroupType.ACCOUNT_GROUP;
    else if (flag & GroupType.APP_BASIC_GROUP > 0)
        groupTypes.Add(GroupType.APP_BASIC_GROUP);

    // ... Other else if ad nauseum ...

    else if (flag & GroupType.SERUCITY_ENABLED > 0)
        groupTypes.Add(GroupType.SECURITY_ENABLED);

    return groupTypes;
}

Если вам действительно нужен ArrayList() по какой-либо причине, вы можете просто сделать return groupTypes.ToArray<int>();

ХТН.

person fourpastmidnight    schedule 15.05.2013
comment
как уже было сказано: Entry.Properties[groupType].Value возвращает -2147483646. Когда я пытаюсь привести его к uint, я получаю InvalidCastException. Поэтому я даже не могу совместить возвращаемое значение с перечислениями. - person wodzu; 15.05.2013
comment
в режиме отладки вы можете видеть, что это целое число со знаком img845.imageshack.us/img845 /2369/grouptype.png - person wodzu; 15.05.2013
comment
подозрительный код - это обходной путь, чтобы прочитать флаг, даже если есть переполнение буфера. На данный момент это работает, если установлены два флага. Сначала я получаю флаг, который не является флагом SERUCITY_ENABLED. Затем я конвертирую заданное значение флага и преобразовываю его в длинное, чтобы восстановить начальное значение, вычитая значение первого флага, чтобы я мог проверить, установлен ли флаг SERUCITY_ENABLED. В частности, я получаю COMException, когда пытаюсь установить флаг следующим образом: var val = (long) ((int) this.Entry.Properties[groupType].Value); this.Entry.Properties[groupType].Value = val & ~0x80000000; - person wodzu; 15.05.2013
comment
этот скриншот показывает, что я получаю ошибку компилятора, когда пытаюсь присвоить 0x80000000 int img692.imageshack.us/img692/6046/errorowc.png - person wodzu; 15.05.2013
comment
это интересно, что вы получаете это маленькое всплывающее окно. У меня не было такой ошибки компиляции (и я скомпилировал), и я даже не получил предупреждения от Visual Studio перед компиляцией. Всплывающее окно не похоже на стандартную ошибку типа Visual Studio. Может быть, инструмент, который вы используете, обманывает вас, заставляя думать, что вы не можете присвоить это значение? Уверяю вас, я могу, я только что выполнил рассматриваемый код. - person fourpastmidnight; 15.05.2013
comment
Теперь, когда я думаю об этом, вы только что упомянули COM. Кажется, я что-то припоминаю, что COM не любит значения long. Перед установкой значения целочисленного типа для COM-объекта убедитесь, что значение .NET является long, и вы возвращаете его к int. - person fourpastmidnight; 15.05.2013
comment
Ведь ты был прав! Мне пришлось вернуться к этому вопросу, и теперь я смог без проблем выполнить приведение к Uint32. Не знаю, что я тогда сделал не так, что он не переводил из Int32 в Uint32. - person wodzu; 19.03.2014
comment
@Paweł Я рад, что ты смог во всем разобраться и что я могу помочь. - person fourpastmidnight; 20.03.2014

Ссылка на ответ @fourpastmidnight и эти статьи object-group-attribute- тип группы и атрибут типа группы msdn, мне удалось найти решение, которое не требует приведения к uint или синтаксического анализа оператора if ... else if.

Увидев отрицательные значения по первой ссылке и из комментария @wodzu к возвращаемому значению -2147483646, я попытался инвертировать значение SECURITY_ENALBED на -0x80000000.

[System.Flags]
public enum GroupType
{
    BUILTIN_LOCAL_GROUP = 0x00000001,
    ACCOUNT_GROUP       = 0x00000002,
    RESOURCE_GROUP      = 0x00000004,
    UNIVERSAL_GROUP     = 0x00000008,
    APP_BASIC_GROUP     = 0x00000010,
    APP_QUERY_GROUP     = 0x00000020,
    SECURITY_ENABLED    = -0x80000000
}

Теперь при получении значения и приведении его к типу GroupType

var groupType = (GroupType)this.Entry.Properties["groupType"].Value

Затем вы можете использовать .ToString() для значения GroupType, которое вернет строку каждого флага, разделенную запятыми.
Или вы можете использовать метод .HasFlag, чтобы проверить, является ли это группой безопасности.

bool IsSecurityGroup = groupType.HasFlag(GroupType.SECURITY_ENABLED);
person Hive    schedule 15.12.2015