Step by Step on how to simulate a client using System Center 2012 Configuration Manager Client SDK
My colleague Adam has a better series of samples of the Client SDK. You can check these blogs here: https://blogs.msdn.com/b/ameltzer/archive/tags/sdk/.
System Center 2012 Configuration Manager SDK RC is now available at: https://www.microsoft.com/download/en/details.aspx?displaylang=en&id=29559
One of the most exciting features of this SDK is the introduction of Configuration Manager Client SDK: Microsoft.ConfigurationManager.Messaging.dll.
“The Configuration Manager Client SDK is an object model and transport for communicating with Configuration Manager site server roles such as the management point for client operations such as registering clients, retrieving policy assignments and bodies, sending inventory, and state/status messages.”
So with it you’re now able to simulate a client to talk with you site servers, send inventory data and state/status messages on behalf of this simulated client. You can leverage it to do performance testing against your hierarchy, fulfill your DB with real client data and showcase the reports to your customers or investigate/troubleshoot the progress of how Configuration Manager site server roles process the messages.
In this article, I will show you the step by step on how to simulate a client based on the Sample.cs in the SDK.
Step 1: Create a certificate
Launch a command line window with administrative right and run the following command to create a self-signed certificate:
makecert -len 2048 -sky exchange -a sha1 -sy 24 -pe -r -n CN=”SCCM Test Certificate" -ss “Test Key Store” -sr LocalMachine
Now run certmgr.msc to open the Certificates Manager mmc:
Find the certificate you just created, right click All Tasks -> Export to export it. At the first page, check box “Yes, export the private key”. Go through the rest of the wizard, use all the default settings and save the pfx file to a location. Do remember the password and you’ll need it later.
Step 2: Create a project (The full sample code is at the end of this article)
1. Add reference to Microsoft.ConfigurationManager.Messaging.dll (After install the SDK, it’s located in <installation folder>\Redistributables) and use them
using Microsoft.ConfigurationManagement.Messaging.Framework;
using Microsoft.ConfigurationManagement.Messaging.Messages;
using Microsoft.ConfigurationManagement.Messaging.Messages.Server;
using Microsoft.ConfigurationManagement.Messaging.Messages.StatusMessages;
using Microsoft.ConfigurationManagement.Messaging.Sender.Http;
2. Add a trace listener to view the log created by Microsoft.ConfigurationManager.Messaging.dll
System.IO.FileStream myTraceLog = new System.IO.FileStream("C:\\myTraceLog.txt", System.IO.FileMode.OpenOrCreate);
// Creates the new trace listener.
System.Diagnostics.TextWriterTraceListener myListener = new System.Diagnostics.TextWriterTraceListener(myTraceLog);
Trace.Listeners.Add(myListener);
3. Add App.config configuration file and edit it to set the trace level.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<switches>
<add name="Messaging Logging" value="Verbose" />
</switches>
<trace autoflush="true" indentsize="3" />
</system.diagnostics>
</configuration>
4. Create a certificate with the pfx file you created at Step 1.
MessageCertificateX509Volatile certificate = new MessageCertificateX509Volatile(File.ReadAllBytes("c:\\MixedModeTestCert.pfx"), "sccm" /* sample cert password */)
*Here, you can use MessageCertificateX509File to bind to a certificate that is already in the certificate store instead of exporting the certificate with private key.
5. Create a ConfigMgrRegistrationRequest instance and set attributes.
ConfigMgrRegistrationRequest registrationRequest = new ConfigMgrRegistrationRequest();
// Add our certificate for message signing
registrationRequest.AddCertificateToMessage(certificate, CertificatePurposes.Signing);
// Set the destination hostname
registrationRequest.Settings.HostName = MPHostname;
registrationRequest.ClientFqdn = ClientName + "." + DomainName;
registrationRequest.NetBiosName = ClientName;
registrationRequest.AgentIdentity = “MySampleApp”;
6. Call RegisterClient function and get SmsClientId.
SmsClientId clientId = registrationRequest.RegisterClient(sender, TimeSpan.FromMinutes(5));
7. After registration finishes, Create a ConfigMgrDataDiscoveryRecordMessage instance and send a DDR message.
ConfigMgrDataDiscoveryRecordMessage ddrMessage = new ConfigMgrDataDiscoveryRecordMessage();
// Add necessary discovery data
ddrMessage.SmsId = clientId;
ddrMessage.ADSiteName = "MyADSite";
ddrMessage.SiteCode = "PE1";
ddrMessage.DomainName = DomainName;
// Add our certificate for message signing
ddrMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing);
ddrMessage.Settings.HostName = MPHostname;
// Now send the message to the MP (it's asynchronous so there won't be a reply)
ddrMessage.SendMessage(sender);
Step 3. Check the result.
1. After RegisterClient call,
Check MP_CliReg.log:
SMS MP Registration Manager started. MP_ClientRegistration 4/25/2012 1:15:52 AM 3240 (0x0CA8)
Check MP_RegistrationManager.log:
Processing Registration request from Client 'test1.cmv58315dom.net' MP_RegistrationManager 4/25/2012 1:15:52 AM 3240 (0x0CA8)
Begin validation of Certificate [Thumbprint D6255A71DA4447E569AAF0FD9581BB54EFDC8624] issued to 'SCCM Test Certificate' MP_RegistrationManager 4/25/2012 1:15:52 AM 3240 (0x0CA8)
Completed validation of Certificate [Thumbprint D6255A71DA4447E569AAF0FD9581BB54EFDC8624] issued to 'SCCM Test Certificate' MP_RegistrationManager 4/25/2012 1:15:52 AM 3240 (0x0CA8)
MP Reg: DDR written to [C:\sms\inboxes\auth\ddm.box\regreq\UQZ00TIW.RDR] for Client [GUID:E10E9679-9F8D-477B-825C-A5F220952B27] with Certificate Thumbprint [D6255A71DA4447E569AAF0FD9581BB54EFDC8624] MP_RegistrationManager 4/25/2012 1:15:52 AM 3240 (0x0CA8)
MP Reg: Processing completed. Completion state = 0 MP_RegistrationManager 4/25/2012 1:15:52 AM 3240 (0x0CA8)
2. After ddrMessage.SendMessage call;
Check MP_Ddr.log:
Mp Message Handler: copying attachment to C:\sms\inboxes\auth\ddm.box\DdrAttachmentPC6MDZ65.xml MP_DdrEndpoint 4/25/2012 1:49:01 AM 5064 (0x13C8)
Inv-Ddr Task: processing xml file "C:\sms\inboxes\auth\ddm.box\DdrAttachmentPC6MDZ65.xml" MP_DdrEndpoint 4/25/2012 1:49:01 AM 5064 (0x13C8)
Full report from client test1, action description = Discovery MP_DdrEndpoint 4/25/2012 1:49:01 AM 5064 (0x13C8)
Ddr Task: Translate report attachment to file "C:\sms\inboxes\auth\ddm.box\TGWYD9X7.DDR" returned 0 MP_DdrEndpoint 4/25/2012 1:49:01 AM 5064 (0x13C8)
Now open the Configuration Manager Console, you should be able to see this client.
Notes & Tips:
1. If you use the same certificate to register the second time with a different name, it will still be regarded as the same machine and update that record. The certificate is always a unique identifier for the client (unless you’re using an ISV proxy client certificate)
2. You can save the SmsClientId returned by the RegisterClient() function. So later, you can send messages on name of this simulating client. If you lose it, you can always re-register to get it with the same certificate.
3. The DDR message is a little tricky. It will get the inventory information on the machine you run this program. You can call .Discover() method to discover everything locally from standard WMI.
If you are interested in the client SDK and are searching for more code samples, please do let me know what scenario you are looking for.
Source Code:
using System;
using System.Text;
using System.IO;
using Microsoft.ConfigurationManagement.Messaging.Framework;
using Microsoft.ConfigurationManagement.Messaging.Messages;
using Microsoft.ConfigurationManagement.Messaging.Messages.Server;
using Microsoft.ConfigurationManagement.Messaging.Messages.StatusMessages;
using Microsoft.ConfigurationManagement.Messaging.Sender.Http;
using System.Diagnostics;
namespace SimulateClient
{
class Program
{
static void Main(string[] args)
{
// Creates the text file that the trace listener will write to.
System.IO.FileStream myTraceLog = new System.IO.FileStream("C:\\myTraceLog.txt", System.IO.FileMode.OpenOrCreate);
// Creates the new trace listener.
System.Diagnostics.TextWriterTraceListener myListener = new System.Diagnostics.TextWriterTraceListener(myTraceLog);
Trace.Listeners.Add(myListener);
string DomainName = "cmv58315dom.net";
string MPHostname = "cmv58317.cmv58315dom.net";
string ClientName = "test2";
SimulateClient(MPHostname, ClientName, DomainName);
}
static void SimulateClient (string MPHostname, string ClientName, string DomainName)
{
HttpSender sender = new HttpSender();
// Load the certificate for client authentication
using (MessageCertificateX509Volatile certificate = new MessageCertificateX509Volatile(File.ReadAllBytes("c:\\MixedModeTestCert.pfx"), "sccm" /* sample cert password */))
{
// Create a registration request
ConfigMgrRegistrationRequest registrationRequest = new ConfigMgrRegistrationRequest();
// Add our certificate for message signing
registrationRequest.AddCertificateToMessage(certificate, CertificatePurposes.Signing);
// Set the destination hostname
registrationRequest.Settings.HostName = MPHostname;
// Discover local properties for registration metadata
registrationRequest.Discover();
registrationRequest.ClientFqdn = ClientName + "." + DomainName;
registrationRequest.NetBiosName = ClientName;
registrationRequest.AgentIdentity = "MySampleApp";
// Register client and wait for a confirmation with the SMSID
SmsClientId clientId = registrationRequest.RegisterClient(sender, TimeSpan.FromMinutes(5));
// Send data to the site
ConfigMgrDataDiscoveryRecordMessage ddrMessage = new ConfigMgrDataDiscoveryRecordMessage();
// Add necessary discovery data
ddrMessage.SmsId = clientId;
ddrMessage.ADSiteName = "MyADSite";
ddrMessage.SiteCode = "PE1";
ddrMessage.DomainName = DomainName;
// Now create inventory records from the discovered data (optional)
ddrMessage.Discover();
// Add our certificate for message signing
ddrMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing);
ddrMessage.Settings.HostName = MPHostname;
// Now send the message to the MP (it's asynchronous so there won't be a reply)
ddrMessage.SendMessage(sender);
}
}
}
}
Comments
Anonymous
May 17, 2012
Hi Minfang, thanks for sharing this code. I tested this code on my lab and i get the fake PC on my CM console, but the client activity is always empty. Is it possible to simulate the fake pc to send a heartbeat, hw/sw inventory, policy request, etc#? if possible, any example? I didn’t find the info on the sdk help files.Anonymous
May 20, 2012
Hi Raphael, Thanks for reading it. Yes I can write the sample to send heartbeat, hw/sw, etc. I will try to finish the sample in the next two weeks. Thanks, MinfangAnonymous
July 03, 2012
hi Minfang, Is there a way to construct DDR message from scratch, rather than using Discover()? i am trying to registered a fake client for a device using ISV proxy. Discover() will bound me to existing client. Any suggestions will be greatly appreciated. Please help. -AlexAnonymous
December 05, 2013
Hi Minfang, Thansk for your post. That's exactly what I was looking for. In our projecct we need to have near 100-200 fake clients for testing. I successfully create them using your example. The only problem I have is: How can I setup additional information (we need IP adress and operation system) for our clients? Appreciate your help.