我对 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 调用。 任何帮助将不胜感激。
谢谢。
如果您确定存在直接规则(来自其他一些查询,或者因为如果没有的话,您永远不会遇到需要此代码的情况),您可以像添加(仅当然调用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