I am working on an application that manages user accounts in Active Directory. I am using the System.DirectoryServices.AccountManagement namespace whereever possible, but I can't figure out how to determine a user's primary group. When I try to remove a group that is the user's primary group I get an exception. Here is my current code:
我正在开发一个管理Active Directory中的用户帐户的应用程序。我尽可能使用System.DirectoryServices.AccountManagement命名空间,但我无法弄清楚如何确定用户的主要组。当我尝试删除作为用户主要组的组时,我得到一个例外。这是我目前的代码:
private void removeFromGroup(UserPrincipal userPrincipal, GroupPrincipal groupPrincipal) {
TODO: Check to see if this Group is the user's primary group.
groupPrincipal.Members.Remove(userPrincipal);
groupPrincipal.Save();
}
Is there a way to get the name of the user's primary group so I can do some validation before trying to remove the user from this group?
有没有办法获取用户的主要组的名称,以便我可以在尝试从该组中删除用户之前进行一些验证?
3 个解决方案
#1
It's quite a messy and involved business - but this code snippet is from my BeaverTail ADSI Browser which I wrote completely in C# (in the .NET 1.1 days) and is known to work - not pretty, but functional:
这是一个非常混乱和涉及的业务 - 但这段代码片段来自我的BeaverTail ADSI浏览器,我完全用C#编写(在.NET 1.1天内)并且已知可以工作 - 不漂亮但功能性:
private string GetPrimaryGroup(DirectoryEntry aEntry, DirectoryEntry aDomainEntry)
{
int primaryGroupID = (int)aEntry.Properties["primaryGroupID"].Value;
byte[] objectSid = (byte[])aEntry.Properties["objectSid"].Value;
StringBuilder escapedGroupSid = new StringBuilder();
// Copy over everything but the last four bytes(sub-authority)
// Doing so gives us the RID of the domain
for(uint i = 0; i < objectSid.Length - 4; i++)
{
escapedGroupSid.AppendFormat("\\{0:x2}", objectSid[i]);
}
//Add the primaryGroupID to the escape string to build the SID of the primaryGroup
for(uint i = 0; i < 4; i++)
{
escapedGroupSid.AppendFormat("\\{0:x2}", (primaryGroupID & 0xFF));
primaryGroupID >>= 8;
}
//Search the directory for a group with this SID
DirectorySearcher searcher = new DirectorySearcher();
if(aDomainEntry != null)
{
searcher.SearchRoot = aDomainEntry;
}
searcher.Filter = "(&(objectCategory=Group)(objectSID=" + escapedGroupSid.ToString() + "))";
searcher.PropertiesToLoad.Add("distinguishedName");
return searcher.FindOne().Properties["distinguishedName"][0].ToString();
}
Hope this helps.
希望这可以帮助。
Marc
#2
The RID of the user's primary group is stored in the 'primaryGroupID' attribute on the user object. You'd have to get the DirectoryEntry for the given user (or user other API's) in order to retrieve this value. After getting that value, you'd have to translate it into a SID for the primary group, and then get the group from that.
用户主要组的RID存储在用户对象的“primaryGroupID”属性中。您必须获取给定用户(或用户其他API)的DirectoryEntry才能检索此值。获得该值后,您必须将其转换为主要组的SID,然后从中获取该组。
There is a KB article that has more detail on this, as well as VB code with how to find the primary group, here: http://support.microsoft.com/kb/297951
有一篇知识库文章有关于此的更多详细信息,以及有关如何查找主要组的VB代码,请访问:http://support.microsoft.com/kb/297951
#3
using (PrincipalContext context = XXX)
{ //get the group
using (GroupPrincipal groupPrincipal =
GroupPrincipal.FindByIdentity(context,IdentityType.SamAccountName, group))
{
if (groupPrincipal != null)
{
//get the user
using (UserPrincipal userPrincipal =
UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName))
{
if (userPrincipal != null)
{
returnValue = userPrincipal.IsMemberOf(groupPrincipal);
}
}
}
}
}
#1
It's quite a messy and involved business - but this code snippet is from my BeaverTail ADSI Browser which I wrote completely in C# (in the .NET 1.1 days) and is known to work - not pretty, but functional:
这是一个非常混乱和涉及的业务 - 但这段代码片段来自我的BeaverTail ADSI浏览器,我完全用C#编写(在.NET 1.1天内)并且已知可以工作 - 不漂亮但功能性:
private string GetPrimaryGroup(DirectoryEntry aEntry, DirectoryEntry aDomainEntry)
{
int primaryGroupID = (int)aEntry.Properties["primaryGroupID"].Value;
byte[] objectSid = (byte[])aEntry.Properties["objectSid"].Value;
StringBuilder escapedGroupSid = new StringBuilder();
// Copy over everything but the last four bytes(sub-authority)
// Doing so gives us the RID of the domain
for(uint i = 0; i < objectSid.Length - 4; i++)
{
escapedGroupSid.AppendFormat("\\{0:x2}", objectSid[i]);
}
//Add the primaryGroupID to the escape string to build the SID of the primaryGroup
for(uint i = 0; i < 4; i++)
{
escapedGroupSid.AppendFormat("\\{0:x2}", (primaryGroupID & 0xFF));
primaryGroupID >>= 8;
}
//Search the directory for a group with this SID
DirectorySearcher searcher = new DirectorySearcher();
if(aDomainEntry != null)
{
searcher.SearchRoot = aDomainEntry;
}
searcher.Filter = "(&(objectCategory=Group)(objectSID=" + escapedGroupSid.ToString() + "))";
searcher.PropertiesToLoad.Add("distinguishedName");
return searcher.FindOne().Properties["distinguishedName"][0].ToString();
}
Hope this helps.
希望这可以帮助。
Marc
#2
The RID of the user's primary group is stored in the 'primaryGroupID' attribute on the user object. You'd have to get the DirectoryEntry for the given user (or user other API's) in order to retrieve this value. After getting that value, you'd have to translate it into a SID for the primary group, and then get the group from that.
用户主要组的RID存储在用户对象的“primaryGroupID”属性中。您必须获取给定用户(或用户其他API)的DirectoryEntry才能检索此值。获得该值后,您必须将其转换为主要组的SID,然后从中获取该组。
There is a KB article that has more detail on this, as well as VB code with how to find the primary group, here: http://support.microsoft.com/kb/297951
有一篇知识库文章有关于此的更多详细信息,以及有关如何查找主要组的VB代码,请访问:http://support.microsoft.com/kb/297951
#3
using (PrincipalContext context = XXX)
{ //get the group
using (GroupPrincipal groupPrincipal =
GroupPrincipal.FindByIdentity(context,IdentityType.SamAccountName, group))
{
if (groupPrincipal != null)
{
//get the user
using (UserPrincipal userPrincipal =
UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName))
{
if (userPrincipal != null)
{
returnValue = userPrincipal.IsMemberOf(groupPrincipal);
}
}
}
}
}