如何在 SCCM (C#) 中将单个资源删除到集合中

问题描述 投票:0回答:1

我对 WMI 的世界还不够熟悉,不知道出了什么问题,但看起来事情应该可以工作,但事实并非如此。

我能够使用以下代码添加资源:

private void Add_SCCM(DirectoryObject selectedObject)
{
    string computerName = selectedObject.Name;

    try
    {
        // Connect to SCCM WMI namespace
        ManagementScope scope = new ManagementScope(@"\\MyCOMPUTER\root\sms\site_XXX");
        scope.Connect();

        // Query ResourceID of the computer
        string query = $"SELECT ResourceID FROM SMS_R_System WHERE Name = '{computerName}'";
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, new ObjectQuery(query));
        ManagementObjectCollection results = searcher.Get();

        string resourceId = null;
        foreach (ManagementObject result in results)
        {
            resourceId = result["ResourceID"]?.ToString();
        }

        if (!string.IsNullOrEmpty(resourceId))
        {
            // Check if the computer is already in the collection as a direct rule
            string ruleQuery = $"SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID = '{SCCM_COLLID}' AND ResourceID = '{resourceId}'";
            ManagementObjectSearcher ruleSearcher = new ManagementObjectSearcher(scope, new ObjectQuery(ruleQuery));
            ManagementObjectCollection ruleResults = ruleSearcher.Get();

            if (ruleResults.Count > 0)
            {
                string infoTitle = "Information";
                string infoMessage = $"Computer {computerName} is already part of the SCCM collection {SCCM_COLLID}. Skipping.";
                MessageBox.Show(infoMessage, infoTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
                return; // Exit without adding
            }

            // Instantiate a direct membership rule
            ManagementClass ruleClass = new ManagementClass(scope, new ManagementPath("SMS_CollectionRuleDirect"), null);
            ManagementObject ruleInstance = ruleClass.CreateInstance();
            ruleInstance["ResourceClassName"] = "SMS_R_System";
            ruleInstance["ResourceID"] = resourceId;
            ruleInstance["RuleName"] = computerName;

            // Add the membership rule to the SCCM collection
            ManagementPath collectionPath = new ManagementPath($"SMS_Collection.CollectionID='{SCCM_COLLID}'");
            ManagementObject collection = new ManagementObject(scope, collectionPath, null);

            ManagementBaseObject inParams = collection.GetMethodParameters("AddMembershipRule");
            inParams["CollectionRule"] = ruleInstance;

            collection.InvokeMethod("AddMembershipRule", inParams, null);

            string successTitle = "Success";
            string successMessage = $"Successfully added {computerName} to SCCM collection {SCCM_COLLID}";
            MessageBox.Show(successMessage, successTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        else
        {
            string errorTitle = "Error";
            string errorMessage = $"Failed to find ResourceID for computer: {computerName}";
            MessageBox.Show(errorMessage, errorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    catch (Exception ex)
    {
        string errorTitle = "Error";
        string errorMessage = $"Error adding {computerName} to SCCM collection {SCCM_COLLID}: {ex.Message}";
        MessageBox.Show(errorMessage, errorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

但是集合上似乎没有“GetRules”方法,因此我可以选择该规则,然后使用 SMS_Collection 类上的 DeleteMembership 方法将其删除。

ChatGPT 建议这样做,但它会导致无效的查询...

// Query the collection rule
string query = $"SELECT * FROM SMS_CollectionRuleDirect WHERE ResourceID IN " +
               $"(SELECT ResourceID FROM SMS_R_System WHERE Name = '{computerName}')";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, new ObjectQuery(query));
ManagementObjectCollection results = searcher.Get();

foreach (ManagementObject rule in results)
{
    rule.Delete();
}

我深陷困境,试图理解 WMI 调用。 任何帮助将不胜感激。

谢谢。

c# wmi sccm wql
1个回答
0
投票

如果您确定存在直接规则(来自其他一些查询,或者因为如果没有的话,您永远不会遇到需要此代码的情况),您可以像添加(仅当然调用DeleteMembershipRule而不是AddMembershipRule)

        // Instantiate a direct membership rule
        ManagementClass ruleClass = new ManagementClass(scope, new ManagementPath("SMS_CollectionRuleDirect"), null);
        ManagementObject ruleInstance = ruleClass.CreateInstance();
        ruleInstance["ResourceClassName"] = "SMS_R_System";
        ruleInstance["ResourceID"] = resourceId;
        ruleInstance["RuleName"] = computerName;

        // Deletethe membership rule from the SCCM collection
        ManagementPath collectionPath = new ManagementPath($"SMS_Collection.CollectionID='{SCCM_COLLID}'");
        ManagementObject collection = new ManagementObject(scope, collectionPath, null);

        ManagementBaseObject inParams = collection.GetMethodParameters("DeleteMembershipRule");
        inParams["CollectionRule"] = ruleInstance;

        collection.InvokeMethod("DeleteMembershipRule", inParams, null);

如果不确定,您可以像这样迭代所有现有规则(示例将删除所有规则)

    // Delete all CollectionRules of a collection
    ManagementBaseObject[] smsCollection = (ManagementBaseObject[])collection["CollectionRules"];
    foreach (ManagementBaseObject col in smsCollection) {
        ManagementBaseObject inParams = collection.GetMethodParameters("DeleteMembershipRule");
        inParams["CollectionRule"] = col;
        collection.InvokeMethod("DeleteMembershipRule", inParams, null);
    }

如果您只想删除特定的规则,则可以在循环中删除所有规则的属性,如下所示:

col["Rulename"]
col["ResourceID"]

然后当您发现要删除的规则时调用DeleteMembershipRule

© www.soinside.com 2019 - 2024. All rights reserved.