Reputation: 481
I'm converting Powershell code to C# and in Powershell I call this API "Get-ADComputer" https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-adcomputer?view=winserver2012-ps. When you look at the examples in the link, it shows an exhaustive list of properties that can be returned.
I'm trying to replicate this in C#, but I get a subset of what the Powershell call returns. For instance, I'm looking for "PrimaryGroup", which is only coming back in the Powershell call.
Here are the code snippets:
POWERSHELL
Get-ADComputer -Filter "*" -Properties "*"
C#
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;
}
}
}
I'm guessing I just haven't quite setup everything correctly in the C# code. I get many of the same properties back, but not all. I'm hoping for guidance.
thanks.
Upvotes: 3
Views: 1339
Reputation: 40898
PowerShell sometimes uses "display names" for the attributes, where the actual name of the attributes in AD are slightly different. PowerShell also has some added properties that translates some of the data in AD to something useful. This is an example of that.
The PrimaryGroup
property returns the distinguished name of the primary group. However, there is no attribute in AD that stores that. The primary group is determined from the primaryGroupId
attribute, which is the RID (Relative Identifier) of the group.
So you have to ask for the primaryGroupId
attribute and translate that to find the actual group. I wrote an article about Finding all of a user’s groups where I shared a method that will do that. This accepts a DirectoryEntry
, but it really just needs to know the primaryGroupId
and the objectSid
(since it uses the user's SID to construct the SID of the group):
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;
}
You should be able to adapt that to pull the values from the DirectorySearcher
.
As a side note, if you don't touch the PropertiesToLoad
collection, it will return every attribute with a value (excluding constructed attributes). That said, it is good practice to use the PropertiesToLoad
if you don't legitimately need to see every attribute.
Upvotes: 3