SDK: In-depth sample on how to use the client messaging SDK–now with ISV proxy registration capabilities

A few months back I posted an in-depth sample performing various functions with the client messaging SDK. I’ve updated the sample to provide the ability to perform ISV proxy registration as well to make it easy to validate basic ISV proxy scenarios.

The sample is basically the same as it was originally but with an additional command, “I” which enables ISV proxy mode. If you type “I” you will need to enter the GUID of the ISV proxy client and then send a registration request. The client GUID will be assigned on behalf of the ISV proxy:

image

Here’s the updated code for quick viewing, and as always, a .cs file is attached at the end of the post.

  1: using System;
  2: using System.Diagnostics;
  3: using System.Diagnostics.CodeAnalysis;
  4: using System.Globalization;
  5: using System.IO;
  6: using Microsoft.ConfigurationManagement.Messaging.Framework;
  7: using Microsoft.ConfigurationManagement.Messaging.Messages;
  8: using Microsoft.ConfigurationManagement.Messaging.Sender.Http;
  9:  
  10: namespace Microsoft.ConfigurationManagement.Messaging.Tools.InteractiveSdkSample
  11: {
  12:     internal class SampleProgram
  13:     {
  14:         private static readonly HttpSender Sender = new HttpSender();
  15:         private static readonly ConsoleTraceListener TraceListener = new ConsoleTraceListener();
  16:         private static MessageCertificateX509 certificate;
  17:         private static SmsClientId clientId;
  18:         private static bool compression;
  19:         private static bool encryption;
  20:         private static SmsClientId isvProxyId;
  21:         private static bool fileLogging;
  22:         private static string mpHostname;
  23:         private static bool replyCompression;
  24:         private static string siteCode;
  25:         private static bool superVerbose;
  26:         private static bool verbose;
  27:  
  28:         /// <summary>
  29:         /// Sets the logging parameters
  30:         /// </summary>
  31:         private static void ChangeLogging()
  32:         {
  33:             if (true == superVerbose)
  34:             {
  35:                 MessagingTrace.TraceSwitch.Level = TraceLevel.Verbose;
  36:             }
  37:             else if (true == verbose)
  38:             {
  39:                 MessagingTrace.TraceSwitch.Level = TraceLevel.Info;
  40:             }
  41:             else
  42:             {
  43:                 MessagingTrace.TraceSwitch.Level = TraceLevel.Warning;
  44:             }
  45:         }
  46:  
  47:         /// <summary>
  48:         /// Writes help to the console and exits
  49:         /// </summary>
  50:         private static void Help()
  51:         {
  52:             Console.WriteLine("{0} <MP Hostname> <SiteCode> [-v|-vv]", Environment.GetCommandLineArgs()[0]);
  53:             Console.WriteLine("This program requires a certificate called MixedModeTestCert.pfx with a password of \"test\"");
  54:             Console.WriteLine("-v: verbose -vv: super-verbose");
  55:             Console.WriteLine("step# is a number for the step to execute");
  56:             WriteSteps();
  57:             Environment.Exit(1);
  58:         }
  59:  
  60:         /// <summary>
  61:         /// Performs initialization, should only be run once
  62:         /// </summary>
  63:         private static void Initialize()
  64:         {
  65:             // Only dump readable characters since we're writing to the console
  66:             HexDumper.OnlyPrintReadable = true;
  67:  
  68:             // Initialize the sender and event handlers
  69:             Sender.OnRawDataSend += OnRawDataSend;
  70:             Sender.OnRawDataReceived += OnRawDataReceived;
  71:             Sender.OnSend += OnSend;
  72:             Sender.OnReceived += OnReceived;
  73:  
  74:             certificate = new MessageCertificateX509Volatile(Path.Combine(Environment.CurrentDirectory, "MixedModeTestCert.pfx"), "test");
  75:  
  76:             if (certificate == null)
  77:             {
  78:                 Console.WriteLine(@"Could not load the test certificate");
  79:                 Environment.Exit(1);
  80:             }
  81:  
  82:             Console.WriteLine(@"Using certificate for client authentication with thumbprint of '{0}'", certificate.Thumbprint);
  83:  
  84:             Trace.Listeners.Add(TraceListener);
  85:             ChangeLogging();
  86:         }
  87:  
  88:         /// <summary>
  89:         /// Input loop that runs when a specific step isn't specified at the command line
  90:         /// </summary>
  91:         [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
  92:         private static void InputLoop()
  93:         {
  94:             while (true)
  95:             {
  96:                 WriteSteps();
  97:                 Console.WriteLine(@"V -- change verbosity level");
  98:                 Console.WriteLine(@"Q -- quit");
  99:                 Console.WriteLine(@"C -- compression enable/disable");
  100:                 Console.WriteLine(@"R -- reply compression enable/disable");
  101:                 Console.WriteLine(@"E -- encryption enable/disable");
  102:                 Console.WriteLine(@"L -- file logging enable/disable");
  103:                 Console.WriteLine(@"I -- ISV proxy mode");
  104:  
  105:                 Console.Write(@"Input: ");
  106:                 ConsoleKeyInfo key = Console.ReadKey();
  107:                 Console.WriteLine();
  108:  
  109:                 switch (key.Key)
  110:                 {
  111:                     case ConsoleKey.L:
  112:                         fileLogging = !fileLogging;
  113:                         Console.WriteLine(@"Setting file logging enabled to: {0}", fileLogging);
  114:                         break;
  115:                     case ConsoleKey.R:
  116:                         replyCompression = !replyCompression;
  117:                         Console.WriteLine(@"Setting reply compression enabled to: {0}", replyCompression);
  118:                         break;
  119:                     case ConsoleKey.E:
  120:                         encryption = !encryption;
  121:                         Console.WriteLine(@"Setting encryption enabled to: {0}", encryption);
  122:                         break;
  123:                     case ConsoleKey.C:
  124:                         compression = !compression;
  125:                         Console.WriteLine(@"Setting compression enabled to: {0}", compression);
  126:                         break;
  127:                     case ConsoleKey.I:
  128:                         Console.Write(@"Enter ISV proxy GUID: ");
  129:                         string guid = Console.ReadLine();
  130:                         isvProxyId = new SmsClientId(guid, true);
  131:                         break;
  132:                     case ConsoleKey.V:
  133:                         if (verbose == false)
  134:                         {
  135:                             Console.WriteLine(@"Changing verbosity to VERBOSE");
  136:                             verbose = true;
  137:                         }
  138:                         else if (superVerbose == false)
  139:                         {
  140:                             Console.WriteLine(@"Changing verbosity to SUPER VERBOSE");
  141:                             superVerbose = verbose = true;
  142:                         }
  143:                         else
  144:                         {
  145:                             Console.WriteLine(@"Changing verbosity to quiet");
  146:                             superVerbose = verbose = false;
  147:                         }
  148:  
  149:                         ChangeLogging();
  150:  
  151:                         break;
  152:                     case ConsoleKey.Q:
  153:                         Console.WriteLine(@"Quitting");
  154:                         Environment.Exit(0);
  155:                         break;
  156:                     case ConsoleKey.D1:
  157:                         PerformOperation(Step.Register);
  158:                         break;
  159:                     case ConsoleKey.D2:
  160:                         PerformOperation(Step.Ddr);
  161:                         break;
  162:                     case ConsoleKey.D3:
  163:                         PerformOperation(Step.Hinv);
  164:                         break;
  165:                     case ConsoleKey.D4:
  166:                         PerformOperation(Step.Sinv);
  167:                         break;
  168:                     case ConsoleKey.D5:
  169:                         PerformOperation(Step.FileCollection);
  170:                         break;
  171:                     case ConsoleKey.D6:
  172:                         PerformOperation(Step.MachinePolicy);
  173:                         break;
  174:                     case ConsoleKey.D7:
  175:                         PerformOperation(Step.UserPolicy);
  176:                         break;
  177:                     default:
  178:                         Console.WriteLine(@"Invalid input received: " + key.KeyChar);
  179:                         break;
  180:                 }
  181:             }
  182:         }
  183:  
  184:         /// <summary>
  185:         /// Main program section
  186:         /// </summary>
  187:         private static void Main(string[] args)
  188:         {
  189:             if (args.Length < 2)
  190:             {
  191:                 Help();
  192:             }
  193:  
  194:             mpHostname = args[0];
  195:             siteCode = args[1];
  196:  
  197:             if (siteCode.Length != 3)
  198:             {
  199:                 Console.WriteLine(@"Invalid site code {0} specified", siteCode);
  200:                 Help();
  201:             }
  202:  
  203:             if (args.Length == 3)
  204:             {
  205:                 if (args[2] == "-v")
  206:                 {
  207:                     verbose = true;
  208:                 }
  209:                 else if (args[2] == "-vv")
  210:                 {
  211:                     verbose = superVerbose = true;
  212:                 }
  213:                 else
  214:                 {
  215:                     Help();
  216:                 }
  217:             }
  218:             else if (args.Length != 2)
  219:             {
  220:                 Help();
  221:             }
  222:  
  223:             Initialize();
  224:             InputLoop();
  225:         }
  226:  
  227:         /// <summary>
  228:         /// Captures raw data received by HTTP sender and logs if superverbose is enabled
  229:         /// </summary>
  230:         private static void OnRawDataReceived(object sender, HttpSenderRawDataEventArgs e)
  231:         {
  232:             if (superVerbose == false && fileLogging == false)
  233:             {
  234:                 return;
  235:             }
  236:  
  237:             if (superVerbose == true)
  238:             {
  239:                 Console.WriteLine(@"Response raw data:");
  240:                 HexDumper.DumpHexToConsole(e.GetRawData());
  241:             }
  242:  
  243:             if (fileLogging == true)
  244:             {
  245:                 string dumpFile = string.Format(CultureInfo.InvariantCulture, "MsgBin_Received_{0}.bin", TimeHelpers.CurrentTimeAsUnixTime);
  246:                 dumpFile = Path.Combine(Path.GetTempPath(), dumpFile);
  247:                 Console.WriteLine("Dumping message to {0}", dumpFile);
  248:                 File.WriteAllBytes(dumpFile, e.GetRawData());
  249:             }
  250:         }
  251:  
  252:         /// <summary>
  253:         /// Captures raw data sent by HTTP sender and logs if superverbose is enabled
  254:         /// </summary>
  255:         private static void OnRawDataSend(object sender, HttpSenderRawDataEventArgs e)
  256:         {
  257:             if (superVerbose == false && fileLogging == false)
  258:             {
  259:                 return;
  260:             }
  261:  
  262:             if (true == superVerbose)
  263:             {
  264:                 Console.WriteLine(@"Send raw data:");
  265:  
  266:                 HexDumper.DumpHexToConsole(e.GetRawData());
  267:             }
  268:  
  269:             if (fileLogging == true)
  270:             {
  271:                 string dumpFile = string.Format(CultureInfo.InvariantCulture, "MsgBin_Sent_{0}.bin", TimeHelpers.CurrentTimeAsUnixTime);
  272:                 dumpFile = Path.Combine(Path.GetTempPath(), dumpFile);
  273:                 Console.WriteLine("Dumping message to {0}", dumpFile);
  274:                 File.WriteAllBytes(dumpFile, e.GetRawData());
  275:             }
  276:         }
  277:  
  278:         /// <summary>
  279:         /// Captures data received by HTTP sender and logs if superverbose is enabled
  280:         /// </summary>
  281:         private static void OnReceived(object sender, MessageSenderEventArgs e)
  282:         {
  283:             if (verbose == false)
  284:             {
  285:                 return;
  286:             }
  287:  
  288:             Console.WriteLine(@"Received payload from MP:");
  289:             Console.WriteLine(e.Message.Body.Payload);
  290:         }
  291:  
  292:         /// <summary>
  293:         /// Captures data sent by HTTP sender and logs if superverbose is enabled
  294:         /// </summary>
  295:         private static void OnSend(object sender, MessageSenderEventArgs e)
  296:         {
  297:             if (verbose == false)
  298:             {
  299:                 return;
  300:             }
  301:  
  302:             Console.WriteLine(@"Sending payload to MP:");
  303:             Console.WriteLine(e.Message.Body.Payload);
  304:  
  305:             if (e.Message.Attachments.Count > 0)
  306:             {
  307:                 if (e.Message is ConfigMgrFileCollectionMessage ||
  308:                     e.Message is ConfigMgrUploadRequest)
  309:                 {
  310:                     Console.WriteLine(@"Not writing attachments for {0} message to console", e.Message);
  311:                     return;
  312:                 }
  313:  
  314:                 for (int i = 0; i < e.Message.Attachments.Count; i++)
  315:                 {
  316:                     Console.WriteLine(@"+======== ATTACHMENT #{0} (name: {1}) ========+", i + 1, e.Message.Attachments[i].Name);
  317:                     Console.WriteLine(e.Message.Attachments[i].Body.Payload);
  318:                 }
  319:             }
  320:         }
  321:  
  322:         /// <summary>
  323:         /// Performs an atomic operation
  324:         /// </summary>
  325:         [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
  326:         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  327:         private static void PerformOperation(Step step)
  328:         {
  329:             // Some steps require a valid client ID to work, this anonymous method ensures this.
  330:             Action checkIsClientIdPresent = () =>
  331:                                                 {
  332:                                                     if (null == clientId)
  333:                                                     {
  334:                                                         throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Cannot execute step #{0:d} {0} because client is not registered.", step));
  335:                                                     }
  336:                                                 };
  337:  
  338:             try
  339:             {
  340:                 Console.WriteLine(@"===========================================================");
  341:                 Console.WriteLine(@"Sending '{0}' message", step);
  342:                 Console.WriteLine(@"===========================================================");
  343:                 switch (step)
  344:                 {
  345:                     case Step.Register:
  346:  
  347:                         ConfigMgrRegistrationRequest regRequest = new ConfigMgrRegistrationRequest();
  348:                         regRequest.Settings.HostName = mpHostname;
  349:                         regRequest.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  350:  
  351:                         // regRequest.Discover();
  352:  
  353:                         // Manual registration
  354:                         // Required: must supply a NetBIOS hostname
  355:                         regRequest.NetBiosName = "MyDummyHostName";
  356:  
  357:                         // Required: must supply an agent identity (this is the name of your client)
  358:                         regRequest.AgentIdentity = "MyCustomClient.exe";
  359:  
  360:                         // Required: must supply a client FQDN
  361:                         regRequest.ClientFqdn = "MyDummyHostName.MyDomain.net";
  362:  
  363:                         if (null != isvProxyId)
  364:                         {
  365:                             Console.WriteLine("Registering as ISV proxy client");
  366:                             regRequest.SigningSmsId = isvProxyId;
  367:                             regRequest.AgentType = ClientRegistrationAgentType.IsvProxyClient;
  368:                         }
  369:  
  370:                         regRequest.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  371:                         regRequest.Settings.ReplyCompression = (true == replyCompression) ? MessageCompression.Zlib : MessageCompression.None;
  372:                         clientId = regRequest.RegisterClient(Sender, TimeSpan.FromMinutes(5));
  373:                         Console.WriteLine(@"Got SMSID from registration of: {0}", clientId);
  374:                         break;
  375:  
  376:                     case Step.Ddr:
  377:                         checkIsClientIdPresent();
  378:  
  379:                         ConfigMgrDataDiscoveryRecordMessage ddrMessage = new ConfigMgrDataDiscoveryRecordMessage();
  380:                         ddrMessage.Settings.HostName = mpHostname;
  381:                         ddrMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  382:                         ddrMessage.SmsId = clientId;
  383:                         ddrMessage.SiteCode = siteCode;
  384:                         ddrMessage.ADSiteName = "MyADSiteName";
  385:                         ddrMessage.DomainName = "MyDomain.net";
  386:                         ddrMessage.NetBiosName = "MyDummyHostName";
  387:                         ddrMessage.ClientVersion = new ClientVersionV5();
  388:                         ddrMessage.Discover();
  389:                         ddrMessage.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  390:                         ddrMessage.Settings.Security.EncryptMessage = encryption;
  391:                         ddrMessage.SendMessage(Sender);
  392:                         break;
  393:  
  394:                     case Step.Hinv:
  395:                         checkIsClientIdPresent();
  396:  
  397:                         ConfigMgrHardwareInventoryMessage hinvMessage = new ConfigMgrHardwareInventoryMessage();
  398:                         hinvMessage.Settings.HostName = mpHostname;
  399:                         hinvMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  400:                         hinvMessage.SmsId = clientId;
  401:                         hinvMessage.SiteCode = siteCode;
  402:                         hinvMessage.NetBiosName = "MyDummyHostName";
  403:                         hinvMessage.DomainName = "MyDomain.net";
  404:                         hinvMessage.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  405:                         hinvMessage.Settings.Security.EncryptMessage = encryption;
  406:                         hinvMessage.AddInstancesToInventory(WmiClassToInventoryReportInstance.WmiClassToInventoryInstances(@"root\cimv2", "Win32_LogicalDisk", @"root\cimv2\sms", "SMS_LogicalDisk"));
  407:                         hinvMessage.AddInstancesToInventory(WmiClassToInventoryReportInstance.WmiClassToInventoryInstances(@"root\cimv2", "Win32_Processor", @"root\cimv2\sms", "SMS_Processor"));
  408:                         hinvMessage.AddInstancesToInventory(WmiClassToInventoryReportInstance.WmiClassToInventoryInstances(@"root\cimv2", "Win32_SystemDevices", @"root\cimv2\sms", "SMS_SystemDevices"));
  409:                         hinvMessage.SendMessage(Sender);
  410:                         break;
  411:  
  412:                     case Step.Sinv:
  413:                         checkIsClientIdPresent();
  414:  
  415:                         ConfigMgrSoftwareInventoryMessage sinvMessage = new ConfigMgrSoftwareInventoryMessage();
  416:                         sinvMessage.Settings.HostName = mpHostname;
  417:                         sinvMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  418:                         sinvMessage.SmsId = clientId;
  419:                         sinvMessage.SiteCode = siteCode;
  420:                         sinvMessage.NetBiosName = "MyDummyHostName";
  421:                         sinvMessage.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  422:                         sinvMessage.Settings.Security.EncryptMessage = encryption;
  423:                         sinvMessage.AddDirectoryFilesToInventory(Environment.ExpandEnvironmentVariables(@"%WINDIR%\system32"), "*.exe", true, true);
  424:                         InventoryInstanceElementFileSystemFile fakeFile = new InventoryInstanceElementFileSystemFile();
  425:                         fakeFile.LastWriteDate = TimeHelpers.Epoch.AddDays(-200);
  426:                         fakeFile.FileVersion = "1.0";
  427:                         fakeFile.FileDescription = "Fake File";
  428:                         fakeFile.CompanyName = "Fake Company";
  429:                         fakeFile.FileName = "FakeFile.EXE";
  430:                         fakeFile.FilePath = Environment.ExpandEnvironmentVariables(@"%SYSTEMDRIVE%\MyFakeFile.EXE");
  431:                         fakeFile.ProductName = "Fake Product";
  432:                         fakeFile.ProductVersion = "1.0";
  433:                         fakeFile.Size = 1024;
  434:                         sinvMessage.AddFileSystemFileInstanceToInventory(fakeFile);
  435:                         sinvMessage.SendMessage(Sender);
  436:                         break;
  437:  
  438:                     case Step.FileCollection:
  439:                         checkIsClientIdPresent();
  440:  
  441:                         ConfigMgrFileCollectionMessage fcMessage = new ConfigMgrFileCollectionMessage();
  442:                         fcMessage.Settings.HostName = mpHostname;
  443:                         fcMessage.Settings.BitsUpload = true;
  444:                         fcMessage.Discover();
  445:                         fcMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  446:                         fcMessage.SmsId = clientId;
  447:                         fcMessage.SiteCode = siteCode;
  448:                         fcMessage.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  449:                         fcMessage.Settings.Security.EncryptMessage = encryption;
  450:                         fcMessage.AddDirectoryFilesToCollection(Environment.ExpandEnvironmentVariables(@"%WINDIR%\system32"), "*.log", true, true);
  451:                         fcMessage.SendMessage(Sender);
  452:                         break;
  453:  
  454:                     case Step.UserPolicy:
  455:                         checkIsClientIdPresent();
  456:                         ConfigMgrPolicyAssignmentRequest userPolicyMessage = new ConfigMgrPolicyAssignmentRequest();
  457:                         userPolicyMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  458:                         userPolicyMessage.Settings.HostName = mpHostname;
  459:                         userPolicyMessage.ResourceType = PolicyAssignmentResourceType.User;
  460:                         userPolicyMessage.Settings.Security.AuthenticationScheme = AuthenticationScheme.Ntlm;
  461:                         userPolicyMessage.Settings.Security.AuthenticationType = AuthenticationType.WindowsAuth;
  462:                         userPolicyMessage.SmsId = clientId;
  463:                         userPolicyMessage.SiteCode = siteCode;
  464:                         userPolicyMessage.Discover();
  465:                         userPolicyMessage.SendMessage(Sender);
  466:                         userPolicyMessage.Settings.Security.EncryptMessage = encryption;
  467:                         userPolicyMessage.Settings.ReplyCompression = (true == replyCompression) ? MessageCompression.Zlib : MessageCompression.None;
  468:                         userPolicyMessage.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  469:                         break;
  470:  
  471:                     case Step.MachinePolicy:
  472:                         checkIsClientIdPresent();
  473:                         ConfigMgrPolicyAssignmentRequest machinePolicyMessage = new ConfigMgrPolicyAssignmentRequest();
  474:                         machinePolicyMessage.Settings.HostName = mpHostname;
  475:                         machinePolicyMessage.AddCertificateToMessage(certificate, CertificatePurposes.Signing | CertificatePurposes.Encryption);
  476:                         machinePolicyMessage.Settings.Security.EncryptMessage = encryption;
  477:                         machinePolicyMessage.Settings.Compression = (true == compression) ? MessageCompression.Zlib : MessageCompression.None;
  478:                         machinePolicyMessage.Settings.ReplyCompression = (true == replyCompression) ? MessageCompression.Zlib : MessageCompression.None;
  479:                         machinePolicyMessage.ResourceType = PolicyAssignmentResourceType.Machine;
  480:                         machinePolicyMessage.SmsId = clientId;
  481:                         machinePolicyMessage.SiteCode = siteCode;
  482:                         machinePolicyMessage.Discover();
  483:                         machinePolicyMessage.SendMessage(Sender);
  484:  
  485:                         break;
  486:                 }
  487:  
  488:                 Console.WriteLine(@"===========================================================");
  489:                 Console.WriteLine(@"Successfully sent '{0}' message!", step);
  490:                 Console.WriteLine(@"===========================================================");
  491:             }
  492:             catch (Exception e)
  493:             {
  494:                 e.RethrowCriticalException();
  495:                 Console.WriteLine();
  496:                 MessagingTrace.TraceException("Got unexpected exception while executing messaging step #{0:d}: '{0}'", e, step);
  497:                 Console.WriteLine(@"===========================================================");
  498:                 Console.WriteLine(@"Failed to send '{0}' message!", step);
  499:                 Console.WriteLine(@"===========================================================");
  500:             }
  501:         }
  502:  
  503:         /// <summary>
  504:         /// Writes the various steps that can be executed with this program to the console
  505:         /// </summary>
  506:         private static void WriteSteps()
  507:         {
  508:             Console.WriteLine(@"1 -- register client");
  509:             Console.WriteLine(@"2 -- send DDR");
  510:             Console.WriteLine(@"3 -- send hardware inventory");
  511:             Console.WriteLine(@"4 -- send software inventory");
  512:             Console.WriteLine(@"5 -- send collected files");
  513:             Console.WriteLine(@"6 -- request machine policy");
  514:             Console.WriteLine(@"7 -- request user policy");
  515:         }
  516:  
  517:         #region Nested type: Step
  518:  
  519:         /// <summary>
  520:         /// Steps supported by this sample
  521:         /// </summary>
  522:         private enum Step
  523:         {
  524:             /// <summary>
  525:             /// None (implementation implies manual selection loop)
  526:             /// </summary>
  527:             None = 0, 
  528:  
  529:             /// <summary>
  530:             /// Register client
  531:             /// </summary>
  532:             Register = 1, 
  533:  
  534:             /// <summary>
  535:             /// Send DDR
  536:             /// </summary>
  537:             Ddr = 2, 
  538:  
  539:             /// <summary>
  540:             /// Send HINV
  541:             /// </summary>
  542:             Hinv = 3, 
  543:  
  544:             /// <summary>
  545:             /// Send SINV
  546:             /// </summary>
  547:             Sinv = 4, 
  548:  
  549:             /// <summary>
  550:             /// Send collected files
  551:             /// </summary>
  552:             FileCollection = 5, 
  553:  
  554:             /// <summary>
  555:             /// Request machine policy
  556:             /// </summary>
  557:             MachinePolicy = 6, 
  558:  
  559:             /// <summary>
  560:             /// Request user policy
  561:             /// </summary>
  562:             UserPolicy = 7, 
  563:         }
  564:  
  565:         #endregion
  566:     }
  567: }

Download the code sample: program.cs