英文:
What is the C# equivalent code for the Powershell sript to remove user from Adminstrators group?
问题
以下是您要翻译的内容:
using (PrincipalContext ctx = new PrincipalContext(ContextType.Machine))
{
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.Name, args[0]);
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, "Administrators");
if (user != null && group != null)
{
try
{
if (group.Members.Remove(user))
{
Console.WriteLine("User successfully removed from Local Administrators.");
}
else
{
Console.WriteLine("User is not a Local Administrator1.");
}
}
catch (Exception ex)
{
Console.WriteLine("User is not a Local Administrator.");
Console.WriteLine(ex.ToString());
}
}
else
{
Console.WriteLine("User was not found.");
}
}
请注意,代码部分不要翻译。
英文:
I have a PowerShell script. It is to remove the user from the Administrators group. It's working fine for local and domain users both.
Remove-LocalGroupMember -Group "Administrators" -Member "Admin02"
I want to implement this in C#. I have tried the below code. But it's not working for the domain account.
using (PrincipalContext ctx = new PrincipalContext(ContextType.Machine))
{
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.Name, args[0]);
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, "Administrators");
if (user != null && group != null)
{
try
{
if (group.Members.Remove(user))
{
Console.WriteLine("User successfully removed from Local Administrators.");
}
else
{
Console.WriteLine("User is not a Local Administrator1.");
}
}
catch (Exception ex)
{
Console.WriteLine("User is not a Local Administrator.");
Console.WriteLine(ex.ToString());
}
}
else
{
Console.WriteLine("User was not found.");
}
}
Its printing User was not found.
I have tried with ContextType.Domain
as well.
Edit: Thank you @Gabriel Luci. for providing the solution. I tried his solution, but there is a challenge with it.
I have a domain user name T1/spreda (forward slash).
But when I run your code and see the value of member, it shows users like this (with back slash). I have written this code to check the user.
var group = new DirectoryEntry("WinNT://./Administrators");
foreach (var m in (IEnumerable)group.Invoke("Members"))
{
var member = new DirectoryEntry(m);
var str = JsonConvert.SerializeObject(member);
Console.WriteLine(str);
//if (str.Contains(args[0]))
//{
// Console.WriteLine("Found");
// var returnVal = group.Invoke("Remove", new[] { member.Path });
// Console.WriteLine(returnVal.ToString());
// break;
So Is there a way to handle this?
答案1
得分: 1
使用AccountManagement
命名空间来处理(GroupPrincipal
/UserPrincipal
)的问题在于创建对象时会加载所有属性。这意味着需要连接到AD以创建AD用户的UserPrincipal
对象,但我们不需要这样做来从组中移除用户。
您可以使用DirectoryEntry
来执行此操作,而GroupPrincipal
和UserPrincipal
在幕后也使用它。代码如下:
var group = new DirectoryEntry("WinNT://./Administrators");
foreach (var m in (IEnumerable)group.Invoke("Members"))
{
var member = new DirectoryEntry(m);
if (member.Name == args[0]) {
group.Invoke("Remove", new [] {member.Path});
break;
}
}
这使用了WinNT提供程序(而不是LDAP)来加载本地组。.
表示本地计算机。如果要从远程计算机加载管理员组,可以将计算机名称放入路径中,如WinNT://computer1/Administrators
。
DirectoryEntry
是本机Windows C++ COM ADSI对象的包装器。在这种情况下,因为我们正在加载一个组,它是一个IADsGroup
对象。我们使用DirectoryEntry.Invoke()
来调用底层对象的方法。因此,group.Invoke("Members")
调用IADsGroup::Members
,它返回成员列表。同样,group.Invoke("Remove", new [] {member.Path})
调用IADsGroup::Remove
来移除成员。
我总是更喜欢使用DirectoryEntry
,即使纯粹处理AD对象时也是如此。它让您更好地控制性能。我在我写的一篇文章中讨论了这一点:Active Directory: Better performance。
英文:
The problem with using the AccountManagement
namespace for this (GroupPrincipal
/UserPrincipal
) is that the act of creating the object loads all the properties. That means that it needs to connect to AD to create a UserPrincipal
object of an AD user, but we don't need to to do that to remove a user from a group.
You can do this with DirectoryEntry
, which GroupPrincipal
and UserPrincipal
use behind the scenes anyway. It would look like this:
var group = new DirectoryEntry("WinNT://./Administrators");
foreach (var m in (IEnumerable)group.Invoke("Members"))
{
var member = new DirectoryEntry(m);
if (member.Name == args[0]) {
group.Invoke("Remove", new [] {member.Path});
break;
}
}
This uses the WinNT provider (as opposed to LDAP) to load the local group. The .
means the local computer. If you wanted to load the Administrators group from a remote computer, you can put the computer name in the path, like WinNT://computer1/Administrators
.
DirectoryEntry
is a wrapper around the native Windows C++ COM ADSI objects. In this case, because we're loading a group, it's an IADsGroup
object. We use DirectoryEntry.Invoke()
to call a method from the underlying object. So group.Invoke("Members")
calls IADsGroup::Members
, which returns a list of the members. Likewise, group.Invoke("Remove", new [] {member.Path})
calls IADsGroup::Remove
to remove the member.
I always prefer using DirectoryEntry
, even when working purely with AD objects. It gives you far more control over performance. I talked about that in an article I wrote: Active Directory: Better performance
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论