使用C#读取组策略设置

20

我该如何在AD域中遍历给定GPO(使用名称或GUID)中可用和/或已设置的设置?而无需使用PowerShell等导出到XML / HTML。

我正在使用C#(.NET 4.0)。


你好,最终你使用了什么方法来迭代 GPO 中的设置? - Praveen Kumar
正如我在接受的答案中所评论的那样,我最终导出了XML文件并进行了编程比较。有关XML比较选项,您可以参考此SO线程:http://stackoverflow.com/questions/9713406/free-xml-compare-tool - Nasir
4个回答

11

非常感谢。我会查看这些链接,希望能够得出一些有用的东西。稍后今天会发布结果。 - Nasir
好的...有机会玩了一下COM接口。GPMC库提供的COM接口没有提供迭代设置的方法。有两个庞大的GenerateReport和GenerateReportToFile函数。我会继续探索看看是否还有其他发现,但目前我想做XML报告并比较所需的元素。感谢您的指导。 - Nasir

5

我有一个类似的问题,不想下载和安装Microsoft GPO库(Microsoft.GroupPolicy.Management)。我希望使用System.DirectoryServices完成所有操作。需要一些挖掘,但是可以实现。

首先,使用DirectorySearcher检索容器。您需要先打开目录条目以将其传递给搜索器。您需要的筛选器是:

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

你需要的属性名称是"gPLink",因此创建一个包含该属性的数组:

string[] requestProperties = { "gPLink" };

现在检索结果,如果可用,请提取gPLink。
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;

如果gpLink为null,则该容器(OU)没有关联的GPO。否则,gpLink将包含类似于以下字符串的内容:
"[LDAP://cn={31B2F340-016D-11D2-945F-00C04FB984F9},cn=policies,cn=system,DC=Test,DC=Domain;0]"

在上面的文本中,您可以看到GPO的CN。现在我们需要从DC检索GPO。
为此,我们使用以下类似的过滤器:
string filter = "(&" +
    "(objectClass=groupPolicyContainer)" +
    "(cn={31B2F340-016D-11D2-945F-00C04FB984F9}))";

您需要创建一个包含以下内容的属性数组:

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

现在使用DirectorySearcher检索GPO。您将在结果中获得一个DirectoryEntry,其中包含属性集合中的所有上述字段。其中一些是COM对象,因此您需要适当处理它们。

感谢您的回答。然而,原问题是关于如何枚举ADM/ADMX文件定义的实际策略和设置以及存储在GPO中的内容。您的回答并未解决这个问题。 - Nasir
这是一个非常有趣的答案......尽管它并没有直接回答这个问题 :-) - Ahmed Masud

1

这里有一个比上面更好、更完整的例子。

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();
    }
}

1

更新:工作副本。现在您可以使用C#读取和解析给定的GPO,而无需使用PowerShell或将任何内容写入磁盘。

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
        }
    }            
}

这里使用了组策略管理控制台(GPMC)工具: https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa814316(v=vs.85).aspx

Microsoft.GroupPolicy 命名空间 https://msdn.microsoft.com/zh-cn/library/windows/desktop/microsoft.grouppolicy(v=vs.85).aspx


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