如何循环遍历 PropertyCollection?

25

有人可以提供一个示例,说明如何遍历System.DirectoryServices.PropertyCollection并输出属性名称和值吗?

我在使用C#。

@JaredPar - PropertyCollection没有Name/Value属性。它有PropertyNames和Values属性,类型为System.Collection.ICollection。我不知道构成PropertyCollection对象的基线对象类型是什么。

@JaredPar再次提醒-我最初错误地使用了错误的类型标签。那是我的错。

更新:根据Zhaph - Ben Duguid的建议,我编写了以下代码。

using System.Collections;
using System.DirectoryServices;

public void DisplayValue(DirectoryEntry de)
{
    if(de.Children != null)
    {
        foreach(DirectoryEntry child in de.Children)
        {
            PropertyCollection pc = child.Properties;
            IDictionaryEnumerator ide = pc.GetEnumerator();
            ide.Reset();
            while(ide.MoveNext())
            {
                PropertyValueCollection pvc = ide.Entry.Value as PropertyValueCollection;

                Console.WriteLine(string.Format("Name: {0}", ide.Entry.Key.ToString()));
                Console.WriteLine(string.Format("Value: {0}", pvc.Value));                
            }
        }      
    }  
}
10个回答

31

在观察窗口中查看 PropertyValueCollection 的值以识别它包含的元素类型,并可以展开其进一步查看每个元素具有的属性。

补充 @JaredPar 的代码


PropertyCollection collection = 获取集合();
foreach ( PropertyValueCollection value in collection ) {
  // 处理值
  Console.WriteLine(value.PropertyName); // 属性名
  Console.WriteLine(value.Value); // 值
  Console.WriteLine(value.Count); // 数量
}

编辑:PropertyCollection由PropertyValueCollection组成。


这是正确的方法,似乎 PropertyValueCollection 是正确枚举的关键。所有其他解决方案都建议使用另一种间接索引(或者根本不起作用)。 - Csaba Toth
完美,只是在我的情况下,我需要在.Value上使用.ToString,因为它不能被隐式转换。 - Chad

6

PropertyCollection有一个PropertyName集合 - 这是一个字符串的集合(参见 PropertyCollection.ContainsPropertyCollection.Item,两者都需要一个字符串)。

通常可以调用GetEnumerator来允许您枚举整个集合,使用通常的枚举方法 - 在这种情况下,您将获取包含字符串键的IDictionary,然后是每个项目/值的对象。


在 foreach 循环中,最好使用隐式转换。 - user76071

5
usr = result.GetDirectoryEntry();
foreach (string strProperty in usr.Properties.PropertyNames)
{
   Console.WriteLine("{0}:{1}" ,strProperty, usr.Properties[strProperty].Value);
}

2
foreach(var k in collection.Keys) 
{
     string name = k;
     string value = collection[k];
}

1
我在另一个帖子上发布了我的答案,然后发现这个帖子问了一个类似的问题。
我尝试了建议的方法,但是当转换为DictionaryEntry时,我总是会得到无效的转换异常。而且对于DictionaryEntry,像FirstOrDefault这样的东西很奇怪。所以,我只是这样做:
var directoryEntry = adUser.GetUnderlyingObject() as DirectoryEntry;
directoryEntry.RefreshCache();
var propNames = directoryEntry.Properties.PropertyNames.Cast<string>();
var props = propNames
    .Select(x => new { Key = x, Value = directoryEntry.Properties[x].Value.ToString() })
    .ToList();

有了这个设置,我可以直接通过键轻松查询任何属性。使用合并和安全导航运算符可使默认值为空字符串或其他内容。
var myProp = props.FirstOrDefault(x => x.Key == "someKey"))?.Value ?? string.Empty;

如果我想查看所有的道具,可以使用类似的foreach循环。
foreach (var prop in props)
{
     Console.WriteLine($"{prop.Key} - {prop.Value}");
}

请注意,“adUser”对象是UserPrincipal对象。

0
我不确定为什么这么难找到答案,但使用下面的代码,我可以循环遍历所有属性并提取出我想要的属性,并将该代码重用于任何属性。 如果您愿意,可以以不同方式处理目录条目部分。
getAnyProperty("[servername]", @"CN=[cn name]", "description");

   public List<string> getAnyProperty(string originatingServer, string distinguishedName, string propertyToSearchFor)
    {
        string path = "LDAP://" + originatingServer + @"/" + distinguishedName;
        DirectoryEntry objRootDSE = new DirectoryEntry(path, [Username], [Password]);
// DirectoryEntry objRootDSE = new DirectoryEntry();

        List<string> returnValue = new List<string>();
        System.DirectoryServices.PropertyCollection properties = objRootDSE.Properties;
        foreach (string propertyName in properties.PropertyNames)
        {
            PropertyValueCollection propertyValues = properties[propertyName];
            if (propertyName == propertyToSearchFor)
            {
                foreach (string propertyValue in propertyValues)
                {
                    returnValue.Add(propertyValue);
                }
            }
        }

        return returnValue;
    }

0

编辑 我误读了OP,以为是PropertyValueCollection而不是PropertyCollection。保留帖子因为其他帖子在引用它。

我不确定我理解你的问题。你只是想循环遍历集合中的每个值吗?如果是这样,这段代码将起作用。

PropertyValueCollection collection = GetTheCollection();
foreach ( object value in collection ) {
  // Do something with the value
}

打印出名称/值

Console.WriteLine(collection.Name);
Console.WriteLine(collection.Value);

0

如果你只想要几个项目,那么你真的不需要做任何神奇的事情...

使用语句:System、System.DirectoryServices 和 System.AccountManagement

public void GetUserDetail(string username, string password)
{
    UserDetail userDetail = new UserDetail();
    try
    {
        PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "mydomain.com", username, password);

        //Authenticate against Active Directory
        if (!principalContext.ValidateCredentials(username, password))
        {
            //Username or Password were incorrect or user doesn't exist
            return userDetail;
        }

        //Get the details of the user passed in
        UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, principalContext.UserName);

        //get the properties of the user passed in
        DirectoryEntry directoryEntry = userPrincipal.GetUnderlyingObject() as DirectoryEntry;

        userDetail.FirstName = directoryEntry.Properties["givenname"].Value.ToString();
        userDetail.LastName = directoryEntry.Properties["sn"].Value.ToString();
    }
    catch (Exception ex)
    {
       //Catch your Excption
    }

    return userDetail;
}

0
public string GetValue(string propertyName, SearchResult result)
{
    foreach (var property in result.Properties)
    {
        if (((DictionaryEntry)property).Key.ToString() == propertyName)
        {
            return ((ResultPropertyValueCollection)((DictionaryEntry)property).Value)[0].ToString();
        }
    }
    return null;
}

-1

我认为有一种更简单的方法

foreach (DictionaryEntry e in child.Properties) 
{
    Console.Write(e.Key);
    Console.Write(e.Value);
}

当我使用这个时,出现了System.InvalidCastException:指定的转换无效。 - Despertar
这是正确的方法论,但使用了错误的类型。PropertyCollection包含PropertyValueCollection对象,根据shahkalpesh的答案,而不是DictionaryEntry对象。 - Bloopy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接