使用GroupPrincipal和SAM PrincipalContext无法解释的InvalidOperationException

时间:2010-01-18 14:53:34

标签: c# api properties principal

我正在尝试像这样创建一个Principal:

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 个答案:

答案 0 :(得分:7)

回答重写

我有你的答案,但你可能不太喜欢它。互联网上的信息很少,但在代码中,它是可以解释的:

  • 当您创建GroupPrincipal时,会向其添加Context。此Context在内部属于隐藏类型:SAMStoreCtx,它继承自抽象类型StoreCtx;
  • 您调用的GroupPrincipal上的每个属性都将调用IsStalidProperty,它是SamStoreCtx的内部成员;
  • 但是,对于Name属性,它不会这样做;
  • 在SAMStoreCtx中,有一段代码如下(反射器输出):

    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进行比较的行总是会产生ObjectMask.None。第二个if语句因此始终为真
  • 当此方法返回false时,调用代码(Description Settor of Description)会抛出异常。

我认为这是Microsoft库中的一个错误。它只发生在SAMStoreCtx上。也许它是有目的的,但因为代码存在但总是返回false使我相信程序员打算使用or-operator代替。使用DisplayName等其他属性检查我的发现会引发与预期相同的异常。

您可以与Microsoft联系并向他们展示此主题。我没有检查.NET 4.0的新版本,这可能会有所不同。您可以通过下载Reflector并加载相关的.NET程序集来自行检查。

编辑:我已经为您联系了Microsoft,并通过connect.microsoft.com here报告了该错误。如果您愿意,可以在那里关注问题。

答案 1 :(得分:2)

您可以使用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();