C# .NET获取AD计算机的完整属性列表(以匹配Powershell获取AD计算机API)
我正在将Powershell代码转换为C#,在Powershell中我将此API称为“Get ADComputer”。当您查看链接中的示例时,它显示了可以返回的属性的详尽列表 我试图在C#中复制这一点,但我得到了Powershell调用返回的一个子集。例如,我正在寻找“PrimaryGroup”,它只会在Powershell调用中返回 以下是代码片段: 动力壳C# .NET获取AD计算机的完整属性列表(以匹配Powershell获取AD计算机API),c#,.net,powershell,active-directory,C#,.net,Powershell,Active Directory,我正在将Powershell代码转换为C#,在Powershell中我将此API称为“Get ADComputer”。当您查看链接中的示例时,它显示了可以返回的属性的详尽列表 我试图在C#中复制这一点,但我得到了Powershell调用返回的一个子集。例如,我正在寻找“PrimaryGroup”,它只会在Powershell调用中返回 以下是代码片段: 动力壳 Get-ADComputer -Filter "*" -Properties "*" C# 使用系统; 使用System.Collec
Get-ADComputer -Filter "*" -Properties "*"
C#
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.DirectoryServices;
使用System.DirectoryServices.ActiveDirectory;
使用System.IO;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
名称空间测试
{
班级计划
{
静态void Main(字符串[]参数)
{
foreach(GetProperties()中的var p)
控制台写入线(p);
}
私有静态IEnumerable GetDomainNames()
{
ICollection域=新列表();
foreach(林中的域。GetCurrentForest().Domains)
domains.Add(domain.Name);
返回域;
}
公共静态列表GetProperties()
{
列表属性=新列表();
foreach(GetDomainNames()中的var domainName)
{
使用(DirectoryEntry DirectoryEntry=newdirectoryentry(@“LDAP://”+domainName))
{
使用(DirectorySearcher mysearch=newdirectorysearcher(directoryEntry))
{
mySearcher.Filter=(“(objectClass=computer)”);
mySearcher.SizeLimit=0;//没有大小限制
mySearcher.PageSize=250;//分页
mySearcher.PropertiesToLoad.Add(“PrimaryGroup”);//只需要此属性,对于测试,请注释掉此行以获取返回的所有属性
foreach(在mySearcher.FindAll()中重新发送搜索结果)
{
foreach(resEnt.Properties.PropertyNames中的var p)
添加(p.ToString());
}
}
}
}
properties.Sort();
归还财产;
}
}
}
我猜我只是没有完全正确地设置C代码中的所有内容。我得到了许多相同的财产,但不是全部。我希望得到指导
谢谢。PowerShell有时会对属性使用“显示名称”,而AD中属性的实际名称略有不同。PowerShell还添加了一些属性,可以将AD中的一些数据转换为有用的内容。这就是一个例子
PrimaryGroup
属性返回主组的可分辨名称。但是,在AD中没有存储该属性的属性。主要组由primaryGroupId
属性确定,该属性是组的RID(相对标识符)
因此,您必须请求primaryGroupId
属性并将其转换为实际的组。我写了一篇文章,介绍了我在哪里分享的一种方法。它接受一个DirectoryEntry
,但它实际上只需要知道primaryGroupId
和objectSid
(因为它使用用户的SID来构造组的SID):
私有静态字符串GetUserPrimaryGroup(DirectoryEntry de){
de.RefreshCache(新[]{“primaryGroupID”,“objectSid”});
//以字符串形式获取用户的SID
var sid=new SecurityIdentifier((字节[])de.Properties[“objectSid”].Value,0.ToString();
//用primaryGroupId替换用户SID的RID部分
//我们只剩下小组的SID了
sid=sid.Remove(sid.LastIndexOf(“-”,StringComparison.Ordinal)+1);
sid=sid+de.Properties[“primaryGroupId”].Value;
//按组的SID查找组
var group=newdirectoryEntry($“LDAP://”);
RefreshCache(新[]{“cn”});
返回组。属性[“cn”]。值为字符串;
}
您应该能够对其进行调整,以便从DirectorySearcher中提取值
作为旁注,如果不触摸
PropertiesToLoad
集合,它将返回每个具有值的属性(不包括构造的属性)。也就是说,如果您不需要合法地查看每个属性,那么最好使用PropertiesToLoad
。感谢Gabriel的回复。但是,在Powershell调用的返回值中,我看到“PrimaryGroup”和“primaryGroupID”,两者的值不同。如果我注释掉“mySearcher.PropertiesToLoad.Add”(“PrimaryGrou”)”,C代码将返回“primaryGroupID”,但不会返回“PrimaryGroup”。是的,这是预期的PrimaryGroup
实际上不存在于AD中。它是一个PowerShell属性,可根据AD中的primaryGroupId
属性查找主组。抱歉,我重新阅读了我的答案,并意识到了为什么我会把您弄糊涂:)我更新了答案,以便更清楚发生了什么,以及如何获取主组。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
class Program
{
static void Main(string[] args)
{
foreach (var p in GetProperties())
Console.WriteLine(p);
}
private static IEnumerable<string> GetDomainNames()
{
ICollection<string> domains = new List<string>();
foreach (Domain domain in Forest.GetCurrentForest().Domains)
domains.Add(domain.Name);
return domains;
}
public static List<string> GetProperties()
{
List<string> properties = new List<string>();
foreach (var domainName in GetDomainNames())
{
using (DirectoryEntry directoryEntry = new DirectoryEntry(@"LDAP://" + domainName))
{
using (DirectorySearcher mySearcher = new DirectorySearcher(directoryEntry))
{
mySearcher.Filter = ("(objectClass=computer)");
mySearcher.SizeLimit = 0; // no size limit
mySearcher.PageSize = 250; // paging
mySearcher.PropertiesToLoad.Add("PrimaryGroup"); // only want this property, for testing, comment out this line to get all properties returned
foreach (SearchResult resEnt in mySearcher.FindAll())
{
foreach (var p in resEnt.Properties.PropertyNames)
properties.Add(p.ToString());
}
}
}
}
properties.Sort();
return properties;
}
}
}
private static string GetUserPrimaryGroup(DirectoryEntry de) {
de.RefreshCache(new[] {"primaryGroupID", "objectSid"});
//Get the user's SID as a string
var sid = new SecurityIdentifier((byte[])de.Properties["objectSid"].Value, 0).ToString();
//Replace the RID portion of the user's SID with the primaryGroupId
//so we're left with the group's SID
sid = sid.Remove(sid.LastIndexOf("-", StringComparison.Ordinal) + 1);
sid = sid + de.Properties["primaryGroupId"].Value;
//Find the group by its SID
var group = new DirectoryEntry($"LDAP://<SID={sid}>");
group.RefreshCache(new [] {"cn"});
return group.Properties["cn"].Value as string;
}