Reading Group Policy Settings using C#
Asked Answered
T

4

20

How do I go about iterating over available and/or set settings in a given GPO (using name or GUID) in an AD domain? Without having to export to XML/HTML using powershell, etc.

I'm using C# (.NET 4.0).

Theomancy answered 15/3, 2011 at 23:35 Comment(2)
Hi finally what method you used to iterate over the settings in a GPO?Actinomycete
As mentioned in my comment to the accepted answer, I ended up exporting XML files and comparing those programmatically. For XML comparison options you can refer to this SO thread: stackoverflow.com/questions/9713406/free-xml-compare-toolTheomancy
B
11

That question got me hyped so I went to research it. So a +1

Some solutions I found from the top being the best to bottom being the worst

Beeswing answered 16/3, 2011 at 4:4 Comment(3)
thank you so much. I'll go over these links and hopefully come up with something functional. Will post back with results later today.Theomancy
alrighty... had a chance to play around with the COM interface. The COM interface provided by the GPMC library does not provide a way to iterate over settings. There are two monolithic GenerateReport and GenerateReportToFile functions. Will keep poking around to see if anyting else turns up, but for now, I think I'll do XML reports and compare the elements I need. Thanks for the directions.Theomancy
All links are deadAirworthy
P
5

I had a similar problem, and didn't want to download and install the Microsoft GPO library (Microsoft.GroupPolicy.Management). I wanted to do it all with System.DirectoryServices. It took a little digging, but it can be done.

First retrieve your container using DirectorySearcher. You'll need to have already opened a directory entry to pass into the searcher. The filter you want is:

string filter = "(&" + "(objectClass=organizationalUnit)" + "(OU=" + container + "))";

and the property you're interested in is named "gPLink", so create an array with that property in it:

string[] requestProperties = { "gPLink" };

Now retrieve the results, and pull out the gPLink, if available.

using (var searcher = new DirectorySearcher(directory, filter, properties, SearchScope.Subtree))
{
    SearchResultCollection results = searcher.FindAll();
    DirectoryEntry entry = results[0].GetDirectoryEntry();
    string gpLink = entry.Properties["gPLink"].Value;

If gpLink is null, there is no GPO associated with the container (OU). Otherwise, gpLink will contain a string such as this:

"[LDAP://cn={31B2F340-016D-11D2-945F-00C04FB984F9},cn=policies,cn=system,DC=Test,DC=Domain;0]"

In the text above, you can see a CN for the GPO. All we need to do now is retrieve the GPO from the DC.

For that, we use a filter that looks like this:

string filter = "(&" +
    "(objectClass=groupPolicyContainer)" +
    "(cn={31B2F340-016D-11D2-945F-00C04FB984F9}))";

You'll want to create a Properties array that include the following:

Properties = { "objectClass", "cn", "distinguishedName", "instanceType", "whenCreated",
    "whenChanged", "displayName", "uSNCreated", "uSNChanged", "showInAdvancedViewOnly",
    "name", "objectGUID", "flags", "versionNumber", "systemFlags", "objectCategory", 
    "isCriticalSystemObject", "gPCFunctionalityVersion", "gPCFileSysPath",
    "gPCMachineExtensionNames", "dSCorePropagationData", "nTSecurityDescriptor" };

Now use DirectorySearcher to retrieve the GPO. You'll get back a DirectoryEntry in the results that contains all of the above fields in the Properties collection. Some are COM objects, so you'll have to handle those appropriately.

Pirogue answered 15/4, 2015 at 14:47 Comment(2)
Thanks for the answer. However, the original question was regarding how to enumerate the actual policies and settings defined by ADM/ADMX files and stored within the GPO. Your answer does not address that.Theomancy
This is a really interesting answer ... even though it doesn't directly address the question :-)Mansard
G
1

UPDATED: Working copy. You can now use c# to get read and parse a given GPO without having to use Powershell or write anything to disk.

using Microsoft.GroupPolicy;

var guid = new Guid("A7DE85DE-1234-F34D-99AD-5AFEDF7D7B4A");
var gpo = new GPDomain("Centoso.local");
var gpoData = gpo.GetGpo(guid);
var gpoXmlReport = gpoData.GenerateReport(ReportType.Xml).ToString();

using (XmlReader reader = XmlReader.Create(new StringReader(gpoXmlReport)))
{
    string field;
    while (reader.MoveToNextAttribute())
    {
        foreach (string attr in attributes)
        {
            // do something
        }
    }            
}

This uses the Group Policy Management Console (GPMC) tools: https://msdn.microsoft.com/en-us/library/windows/desktop/aa814316(v=vs.85).aspx

Microsoft.GroupPolicy Namespace https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.grouppolicy(v=vs.85).aspx

Gaekwar answered 3/5, 2016 at 23:9 Comment(0)
S
1

Here is a better and more complete example then above.

class Program
{
    static void Main(string[] args)
    {
        DirectoryEntry rootDse = new DirectoryEntry("LDAP://rootDSE");
        DirectoryEntry root = new DirectoryEntry("GC://" + rootDse.Properties["defaultNamingContext"].Value.ToString());
        DirectorySearcher searcher = new DirectorySearcher(root);
        searcher.Filter = "(objectClass=groupPolicyContainer)";

        foreach (SearchResult gpo in searcher.FindAll())
        {
            var gpoDesc = gpo.GetDirectoryEntry().Properties["distinguishedName"].Value.ToString();
            Console.WriteLine($"GPO: {gpoDesc}");

            DirectoryEntry gpoObject = new DirectoryEntry($"LDAP://{gpoDesc}");

            try
            {
                Console.WriteLine($"DisplayName: {gpoObject.Properties["displayName"].Value.ToString()}");
            }
            catch
            {
            }

            try
            {
                Console.WriteLine($"PCFileSysPath: {gpoObject.Properties["gPCFileSysPath"].Value.ToString()}");
            }
            catch
            {
            }

            try
            {
                Console.WriteLine($"VersionNumber: {gpoObject.Properties["versionNumber"].Value.ToString()}");
            }
            catch
            {
            }

            try
            {
                Console.WriteLine($"UserExtensionNames: {gpoObject.Properties["gPCUserExtensionNames"].Value.ToString()}");
            }
            catch
            {
            }

            try
            {
                Console.WriteLine($"MachineExtensionNames: {gpoObject.Properties["gPCMachineExtensionNames"].Value.ToString()}");
            }
            catch
            {
            }


            try
            {
                Console.WriteLine($"PCFunctionality: {gpoObject.Properties["gPCFunctionalityVersion"].Value.ToString()}");
            }
            catch
            {
            }

        }

        Console.ReadKey();
    }
}
State answered 11/10, 2016 at 19:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.