Необъяснимое исключение InvalidOperationException с GroupPrincipal и SAM PrincipalContext
Я пытаюсь создать Принципал, как это:
PrincipalContext pc = new PrincipalContext(ContextType.Machine);
GroupPrincipal group = new GroupPrincipal(pc);
group.Name = "Some Group Name";
group.Description = "Some Group Name Description";
group.Save();
Тем не менее, когда код выполняется, я получаю следующее сообщение об исключении:
System.DirectoryServices.AccountManagement: Недопустимое свойство для этого типа магазина.
Если я не установлю Description
Свойство, приведенный выше код прекрасно работает, просто нет описания для группы.
Я делаю что-то неправильно?
Заранее спасибо.
РЕДАКТИРОВАТЬ: я думаю, что я нашел обходной путь для этого (для тех, кто, возможно, заинтересован). Группу можно создать так же, как указано выше:
PrincipalContext pc = new PrincipalContext(ContextType.Machine);
GroupPrincipal group = new GroupPrincipal(pc);
group.Save();
Теперь вы создаете DirectoryEntry
и свяжите это с недавно созданной Группой как это:
string path = "WinNT://" + machineName + "/" + group.SamAccountName;
DirectoryEntry dEntry = new DirectoryEntry(path);
Это позволяет получить доступ к свойствам этой группы, но меня интересует описание, поэтому:
dEntry.Properties["description"].Add("Some Decription");
dEntry.CommitChanges();
И это должно сделать это.
2 ответа
Ответ переписан
У меня есть ваш ответ, но он вам может не понравиться. Информации в интернете мало, но в коде это объяснимо:
- Когда вы создаете свой GroupPrincipal, к нему добавляется контекст. Этот контекст внутренне имеет скрытый тип: SAMStoreCtx, который наследуется от абстрактного типа StoreCtx;
- Каждое свойство в GroupPrincipal, которое вы вызываете, будет вызывать IsValidProperty, внутренний член SamStoreCtx;
- Однако это не относится к свойству Name;
Внутри SAMStoreCtx есть фрагмент кода, который выглядит следующим образом (вывод Reflector):
internal override bool IsValidProperty(Principal p, string propertyName) { ObjectMask none = ObjectMask.None; if (!ValidPropertyMap.TryGetValue(propertyName, out none)) { return false; } if ((MaskMap[p.GetType()] & none) <= ObjectMask.None) { return false; } return true; }
- Посмотрите внимательно на этот код (это заняло у меня мгновение), и вы заметите ошибку. Строка, сравнивающая битовый флаг с
none
использование оператора and всегда приводит к ObjectMask.None. Второе утверждение if для этого всегда верно. - Код вызова (свойство Settor of Description) генерирует исключение, когда этот метод возвращает false.
Я считаю, что это ошибка в библиотеке Microsoft. Это происходит только с SAMStoreCtx. Возможно, это нарочно, но поскольку код присутствует, но всегда возвращает false, я полагаю, что программисты намеревались использовать вместо этого оператор or. Проверка моих результатов с другими свойствами, такими как DisplayName, выдает то же исключение, что и ожидалось.
Вы можете связаться с Microsoft по этому поводу и показать им эту ветку. Я не проверял новые бета-версии.NET 4.0, которые могут отображаться по-другому. Вы можете проверить это сами, загрузив Reflector и загрузив соответствующую сборку.NET.
РЕДАКТИРОВАТЬ: я связался с Microsoft для вас и сообщил об ошибке через connect.microsoft.com здесь. Вы можете следить за вопросом там, если хотите.
Вы можете использовать GetUnderlyingObject, чтобы получить DirectoryEntry для группы вместо ее поиска.
var newGroup = new GroupPrincipal(context, groupName);
// You must save first
newGroup.Save();
var entry = (DirectoryEntry) newGroup.GetUnderlyingObject();
entry.Properties["description"].Add(description);
entry.CommitChanges();