2

次のようなプリンシパルを作成しようとしています。

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();

そして、それはそれを行う必要があります。

4

2 に答える 2

7

Answer rewritten

I've got your answer, but you may not really like it. The information on the internet is scarce, but in code, it is explainable:

  • When you create your GroupPrincipal, a Context is added to it. This Context is internally of a hidden type: SAMStoreCtx, which inherits from an abstract type StoreCtx;
  • Each property on the GroupPrincipal that you call will call IsValidProperty, an internal member of SamStoreCtx;
  • However, it doesn't do so for the Name property;
  • Inside SAMStoreCtx, there's a piece of code that looks as follows (Reflector output):

    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;
    }
    
  • Look closely at that code (it took me a moment) and you'll spot the bug. The line comparing a bit flag to none using the and-operator will always result in ObjectMask.None. The second if-statement is therefor always true.
  • The calling code (the Property Settor of Description) throws an exception when this method returns false.

I believe this to be a bug in the Microsoft library. It only happens with the SAMStoreCtx. Perhaps it is on purpose, but because the code is there but always returns false makes me believe the programmers intended the use of the or-operator instead. Checking my findings with other properties like DisplayName throws the same exception as expected.

You can contact Microsoft about this and show them this thread. I haven't checked the new betas of .NET 4.0 which might show up differently. You can check this for yourself by downloading Reflector and loading the relevant .NET assembly.

EDIT: I've contacted Microsoft for you and reported the bug through connect.microsoft.com here. You can follow the issue there if you like.

于 2010-01-18T14:58:18.933 に答える
3

グループを検索する代わりに、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(); 
于 2012-03-09T12:03:11.140 に答える