Click here to Skip to main content
15,888,216 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi All,

The task i have been given is creating an application that adds a computer into a collection in System Center Configuration Manager 2012 through C#. (I'm using C# as there is certain limitations stopping me from using powershell).

Using the SDK documentation - I have been supplied with a basic function that adds a computer to a collection but it is hard to follow and as im not massively experienced is troubling me.

C#
public static int AddNewComputer(WqlConnectionManager connection, string netBiosName, string smBiosGuid, string macAddress)//, string ComputerName, string CollectionName)
        {
            try
            {
                if (smBiosGuid == null && macAddress == null)
                {
                    throw new ArgumentNullException("smBiosGuid or macAddress must be defined");
                }

                // Reformat macAddress to : separator.
                if (string.IsNullOrEmpty(macAddress) == false)
                {
                    macAddress = macAddress.Replace("-", ":");
                }

                // Create the computer.
                Dictionary<string, object> inParams = new Dictionary<string, object>();
                inParams.Add("NetbiosName", netBiosName);
                inParams.Add("SMBIOSGUID", smBiosGuid);
                inParams.Add("MACAddress", macAddress);
                inParams.Add("OverwriteExistingRecord", false);

                IResultObject outParams = connection.ExecuteMethod(
                    "SMS_Site",
                    "ImportMachineEntry",
                    inParams);

                // Add to All System collection.
                IResultObject collection = connection.GetInstance("SMS_Collection.collectionId='SMS00001'");
                IResultObject collectionRule = connection.CreateEmbeddedObjectInstance("SMS_CollectionRuleDirect");
                collectionRule["ResourceClassName"].StringValue = "SMS_R_System";
                collectionRule["ResourceID"].IntegerValue = outParams["ResourceID"].IntegerValue;

                Dictionary<string, object> inParams2 = new Dictionary<string, object>();
                inParams2.Add("collectionRule", collectionRule);

                collection.ExecuteMethod("AddMembershipRule", inParams2);

                return outParams["ResourceID"].IntegerValue;
            }
            catch (SmsException e)
            {
                Console.WriteLine("failed to add the computer" + e.Message);
                throw;
            }
        }


I am struggling to see where I can implement the actual computer name which the application will gain at run time. And also where to modify which collection the computer will be added to.

Is there anybody with experience in this as the support online is very minimal for this.
Posted

This isn't really the forum for your question as your question doesn't have anything to do with C# but, instead, everything to do with the internals of SCCM and its WMI classes. There's probably only two regular visitors around here who has done any work with SCCM.

But, you got lucky as I'm one of those "regular visitors" who has done extensive work with SCCM and writing tools for it.

You don't need most of your sample code. You'd be better off scrapping what you have and rewriting from scratch. You'll need a few "generic" functions to do stuff like look up a SMS_Collection object by name and return it, as well as one to look up a ResourceId by computer name (refered to as NetBiosName) in the SMS_R_System WMI objects, connect to the site WMI database on the site server, ...

These are the steps to add a computer to a collection:

0) Lookup the SMS_Collection you're adding this computer to. Hang on to this, you'll need it later.

1) You have to lookup the ResourceId for the computer name you're trying to add in the SMS_R_System table on the site server.
      "SELECT ResourceId FROM SMS_R_System WHERE NetbiosName='computerName'"

2) You use the ResourceId to create a SMS_CollectionRuleDirect object on the site server.
      To create one of these, you need to supply three values:
          a) The ResourceClassName, which is always going to be "SMS_R_System".
          b) The ResourceId you got in step 1.
          c) A RuleName, usually just a string containing the computer name your adding.

4) On the SMS_Collection object to got from step 0, call the AddMembershipRule method and pass in the SMS_CollectionRuleDirect object you created in step 2. You'll also supply a QueryId of 0 because your adding a Direct membership rule.

5) Repeat steps 1 through 4 for each computer you're adding to the same collection.

6) Call RequestRefesh on the SMS_CollectionObject you got from step 0.

Done!

No, I can't give you the code I have because it's buried within a libary I spent 3 months writing and I can't post that much code here. I also don't own it as it belongs to my employer.
 
Share this answer
 
Comments
MitchG92_24 30-Apr-13 5:28am    
Hi Dave - Thank you very much for this reply - it has helped me greatly. I now have some code that will add the computer to a collection, however the collection instance is searched for based on collectionID.

IResultObject collection = connection.GetInstance("SMS_Collection.collectionId=" + "'" + collectionName + "'");

I have tried to search via the collection name as i have seen in the SMS_Collection class that this is a valid field - but im getting errors that its thr wrong object path.

IResultObject collection = connection.GetInstance("SMS_Collection.Name=" + "'" + collectionName + "'");

Can you offer me any advice here at all?

Thank you very much
Dave Kreskowiak 30-Apr-13 7:32am    
You can't use GetInstance to get an object by name. It can only be used to get an object by its primary key. You have to use a ManagementObjectSearcher and a SELECT query as above to get it by name.
MitchG92_24 30-Apr-13 7:34am    
ok thank you, i'll get looking into that. You have been a massive help :)
MitchG92_24 30-Apr-13 10:40am    
Hi Dave, was wondering if you could lend any more advice?

I have been trawling the internet all day for answers to my problem with no luck.

string query = "SELECT * WHERE SMS_Collection.Name = 'CollectionName'";

//METHOD ONE - DOESNT WORK - Errors with System.NotImplementedException (although it passes the validity test)

bool querybool = connection.IsQueryValid(query);if (querybool == true){

IResultObject iro = connection.QueryProcessor.ExecuteQuery(query);}

//METHOD 2 - DOESNT WORK - Errors with "INVALID QUERY"

WqlObjectQuery wqlQuery = new WqlObjectQuery(query);

ManagementScope ms = new ManagementScope(@"\\SERVERNAME\root\sms\site_PR1");

ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms,wqlQuery);

ManagementObjectCollection moc = searcher.Get();


Do you have any ideas as to why these methods dont work?
Dave Kreskowiak 30-Apr-13 11:35am    
The query is:
SELECT * FROM SMS_Collection WHERE Name='collectionName'
here is what I am using for Configuration Manager 2007...

C#
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.ConfigurationManagement.ManagementProvider;
using Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine;
using Microsoft.Win32;

namespace AddToCollection
{
    class Program
    {
        static string CollectionName;
        static string SiteServer;
        static string SiteCode;
        static List<string> MachineList;

        static void Main(string[] args)
        {
            SiteServer = SCCM.GetDefaultConnectionInfo("ServerName");
            SiteCode = SCCM.GetDefaultConnectionInfo("SiteCode");
            ParseParams();
            if (CollectionName.Length > 2 && MachineList.Count > 0)
            {
                SCCM WKS = new SCCM(SiteServer, SiteCode);
                WKS.OpenConnection();
                string CollectionId = WKS.GetCollectionId(CollectionName);
                if (CollectionId.Length == 8)
                {
                    List<string> MachinesInCollection = WKS.GetCollection(CollectionId);
                    foreach (string MachineName in MachineList)
                    {
                        if (MachinesInCollection.Contains(MachineName))
                            Console.WriteLine(MachineName + " already in collection.");
                        else
                        {
                            int ResourceId = WKS.GetResourceId(MachineName);
                            if (ResourceId > 1)
                            {
                                if (WKS.AddToCollection(CollectionId, ResourceId))
                                    Console.WriteLine(MachineName + " added.");
                                else
                                    Console.WriteLine(MachineName + " failed to add machine to collection.");
                            }
                        }
                    }
                }
                else
                {
                    System.Threading.Thread.Sleep(5000);
                    Console.WriteLine("Collection not found.");
                    Environment.Exit(12);  
                }
                System.Threading.Thread.Sleep(5000);
                Environment.Exit(0);
            }
            else
            {
                Console.WriteLine("Invalid parameter.");
                Console.WriteLine("AddToCollection "+
                    ");
                System.Threading.Thread.Sleep(5000);
                Environment.Exit(87);
            }
        }

        static void ParseParams()
        {
            MachineList = new List<string>();
            foreach (string item in Environment.GetCommandLineArgs())
            {
                if (item.StartsWith("/") || item.StartsWith("-"))
                {
                    try
                    {
                        string param = item.Substring(1, item.IndexOf(":") - 1).ToUpper();
                        string paramValue = item.Remove(0, item.IndexOf(":")+1);
                        if (param=="SITESERVER" || param=="SERVER")
                            SiteServer = paramValue;
                        if (param == "SITECODE")
                            SiteCode = paramValue;
                        if (param == "MACHINENAME" || param == "HOSTNAME" ||
                            param == "COMPUTERNAME" || param == "MACHINE" ||
                            param == "HOST" || param == "COMPUTER")
                            MachineList.Add(paramValue);
                        if (param == "COLLECTION" || param == "COLLECTIONID" ||
                            param == "COLLECTIONNAME")
                            CollectionName = paramValue;
                        if (param == "FILE" || param == "FILENAME" ||
                            param == "LIST" || param == "MACHINELIST" ||
                            param == "HOSTLIST" || param == "COMPUTERLIST")
                        {
                            foreach (string ComputerName in File.ReadAllLines(paramValue))
                            {
                                if (ComputerName.Trim().Length > 0)
                                    MachineList.Add(ComputerName.Trim().ToUpper());
                            }
                        }
                    }
                    catch { }
                }
            }
        }
    }

    public class SCCM
    {
        private WqlConnectionManager SiteServerConnection;
        private string SiteServerName, SiteServerCode;
        private bool _IsConnected;

        public delegate void ReportProgressHandler(string Message);
        public event ReportProgressHandler ReportProgress;

        public SCCM(string SiteServer, string SiteCode)
        {
            SiteServerName = SiteServer;
            SiteServerCode = SiteCode;
            _IsConnected = false;
        }

        public SCCM()
        {
            SiteServerName = GetDefaultConnectionInfo("ServerName");
            SiteServerCode = GetDefaultConnectionInfo("SiteCode");
        }

        ~SCCM()
        {
            CloseConnection();
        }

        public WqlConnectionManager GetConnectionObject()
        {
            return SiteServerConnection;
        }

        public void OpenConnection()
        {
            if (!_IsConnected)
            {
                SiteServerConnection = new WqlConnectionManager();
                SiteServerConnection.Connect(SiteServerName);
                _IsConnected = true;
            }
        }

        public void CloseConnection()
        {
            if (_IsConnected)
            {
                SiteServerConnection.Close();
                _IsConnected = false;
            }
        }

        public bool Connected
        {
            get { return _IsConnected; }
            set { if (value) OpenConnection(); else CloseConnection(); }
        }

        public static string GetDefaultConnectionInfo(string ValueName)
        {
            RegistryKey ConfigMgrAdminKey = Registry.CurrentUser.OpenSubKey(
                    @"Software\Microsoft\ConfigMgr\Admin UI\MRU\DefaultSite");
            if (ConfigMgrAdminKey == null) return null;
            string result = ConfigMgrAdminKey.GetValue(ValueName).ToString();
            ConfigMgrAdminKey.Close();
            return result;
        }

        public string GetCollectionId(string CollectionName)
        {
            if (CollectionName.Length == 8)
            {
                if (CollectionName.StartsWith(SiteServerCode, StringComparison.CurrentCultureIgnoreCase))
                {
                    string hexValue = CollectionName.Remove(0, 3);
                    try
                    {
                        int decValue = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
                        if (decValue >= 1)
                            return CollectionName;
                    }
                    catch { }
                }
            }
            string wql = "SELECT * FROM SMS_Collection WHERE Name = '{0}'";
            IResultObject CollectionItems = SiteServerConnection.QueryProcessor.ExecuteQuery(String.Format(wql, CollectionName));
            foreach (IResultObject item in CollectionItems)
                return item["CollectionId"].StringValue;
            return null;
        }

        private IResultObject Query(string WQL)
        {
            if (_IsConnected)
                return SiteServerConnection.QueryProcessor.ExecuteQuery(WQL);
            else
                return null;
        }

        public int GetResourceId(string ComputerName)
        {
            try
            {
//                string wql = "SELECT Name FROM SMS_Collection WHERE CollectionID = 'SMS00001' AND Name='" + ComputerName + "'";
                // SMS_Collection can contain invalid machines - use SMS_FullCollectionMembership instead
                string wql = "SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID = 'SMS00001' AND Name='" + ComputerName + "'";
                IResultObject ItemList = Query(wql);
                double i = 0;
                foreach (IResultObject item in ItemList)
                    return item["ResourceID"].IntegerValue;
            }
            catch { Console.WriteLine(ComputerName + " not found."); }
            return -1;
        }

        public List<string> GetCollection(string CollectionNameOrID)
        {
            List<string> SystemList = new List<string>();
            CollectionNameOrID = GetCollectionId(CollectionNameOrID);
            string wql = "SELECT Name FROM SMS_FullCollectionMembership WHERE CollectionID = '{0}'";
            IResultObject ItemList = Query(String.Format(wql, CollectionNameOrID));
            double i = 0;
            foreach (IResultObject item in ItemList)
            {
                SystemList.Add(item["Name"].StringValue);
                if (ReportProgress != null)
                {
                    i += 1;
                    ReportProgress(((i / ItemList.Count) * 100).ToString() + "%");
                }
            }
            return SystemList;
        }

        public bool AddToCollection(string CollectionID, int ResourceID)
        {
            try
            {
                
                IResultObject collection = SiteServerConnection.GetInstance("SMS_Collection.collectionId='"+CollectionID+"'");
                IResultObject collectionRule = SiteServerConnection.CreateEmbeddedObjectInstance("SMS_CollectionRuleDirect");

                collectionRule["ResourceClassName"].StringValue = "SMS_R_System";
                collectionRule["ResourceID"].IntegerValue = ResourceID;
                //collectionRule["Rule_Name"].StringValue = RuleName;

                Dictionary<string,> Params = new Dictionary<string,>();
                Params.Add("collectionRule", collectionRule);

                collection.ExecuteMethod("AddMembershipRule", Params);

                return true;
            }
            catch (SmsException e)
            {
                return false;
            }
        }

    }
}

</string></string></string></string></string></string>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900