1

I'll preface this with I know very little about C# coding. Real good with PowerShell, VBS, etc. But I can at least know enough to be dangerous. We have a C# program that runs locally on the machine. Its purpose is to install the SCCM client and look for the advertised task sequence. for the purpose of this drill, assume the correct task sequence is deployed to the collection this machine is in - I know it's not that - it starts the If block because it finds the advertised TS.

There's a lot of other stuff in the code, but here's the meat and potatoes of the part of the script that is failing. FWIW, this is in a try/catch block and the TS name is "Windows 10 Upgrade". I even renamed the TS thinking it was spaces in it that caused it to fail. No Joy.

ManagementScope scope = new ManagementScope(@"\\localhost\ROOT\ccm\clientsdk");
ObjectQuery query = new ObjectQuery("SELECT * FROM CCM_Program");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
Write_Log("Searching for Policy");

ManagementObjectCollection allpackages = searcher.Get();
     foreach (ManagementObject pkg in allpackages)
     {
          Write_Log(pkg["PackageName"].ToString());
          if (pkg["PackageName"].ToString() == "Windows 10 Upgrade")
          {
               Write_Log("Found:" + pkg["PackageName"].ToString());
               Write_Log("About to execute WMI Invoke for pkg: " + pkg);
               ManagementClass wmiClass = new managementClass(@"\\localhost\ROOT\ccm\clientSDK:CCM_ProgramsManager");
               ManagementBaseObject outMPParams = wmiClass.InvokeMethod("ExecuteProgram", pkg, null);
               Write_Log("ExecuteProgram Result: " + outMPParams["ReturnValue"].ToString());
               if (outMPParams["ReturnValue"].ToString() == "0")
                    Write_Log("SCCM TS Started");
                    Application.Exit();
                }

The localhost gets resolved to the computer name so that's good. The part that is failing is this:

ManagementBaseObject outMPParams = wmiClass.InvokeMethod("ExecuteProgram", pkg, null);

Now it breaks completely out of the try/catch block with "TS not found" and no other errors. What's frustrating is that I loaded in a bunch of Write_log entries to try and catch what the error is, but that one step breaks it real good and goes right to the catch block.

Does anyone have any experience in using C# for SCCM-related tasks? Does the syntax above look correct?

Like I said, I inherited the code from another company and am trying to make it work for us. I just don't know enough about the call and can't find anything online about what it is trying to do.

Any help is MUCH apprecaited!!

DaGbyte
  • 41
  • 4
  • It look somewhat correct. Imo the problem is that CCM_Program does not seem to have any methods so you cannot invoke one. What I gathered from a quick search is that you would have to get the TS from CCM_Program then use CCM_ProgramsManager to execute (see: https://social.technet.microsoft.com/Forums/en-US/092bc15d-7537-4b2b-91fa-e112151e204f/starting-a-task-sequence-using-powershell-and-wmi?forum=configmanagerosd) As this is all wmi and you said you are good with PS/VBS I would advise writing this in a language you know first and then "port" to c# once it works. – Syberdoor Nov 16 '20 at 07:47
  • One additional thing in general: The TS will not have a proper Name (will be *) and even PackageName might not be what you expect, use some WMIExplorer to manually check what it really is and how to properly identify it – Syberdoor Nov 16 '20 at 07:51

1 Answers1

0

Well, it's not the answer I was looking for, but I was able to cob together some PS code that does what I need. First I query what packages are available with this:

$AllPackages = Get-WmiObject -Class ccm_program -Namespace root\ccm\ClientSDK 

Then I tickle the machine policy with this

Invoke-WMIMethod -Namespace root\ccm -Class SMS_CLIENT -Name TriggerSchedule “{00000000-0000-0000-0000-000000000021}” | out-null

wait a little bit then evaluate it with this:

Invoke-WMIMethod -Namespace root\ccm -Class SMS_CLIENT -Name TriggerSchedule “{00000000-0000-0000-0000-000000000022}” | out-null

then I do a ForEach loop to get the info I nned:

ForEach ($Pkg in $AllPackages) {
     $PackageID = $Pkg.PackageID
     $ProgramID = $Pkg.ProgramID
     $PackageName = $Pkg.PackageName

     if ($PackageName -eq $TSName) {

Then ET phones home with

([wmiclass]'root\ccm\ClientSDK:CCM_ProgramsManager').ExecuteProgram($ProgramID, $PackageID)

and that's all she wrote. I do all that in a While block and bust out once it launches.

One question I DO have if anyone is still watching...

How can I get a result back from the WMI call? I tried this

$RetVal=(([wmiclass]'root\ccm\ClientSDK:CCM_ProgramsManager').ExecuteProgram($ProgramID, $PackageID)).ExitCode

But it didn't like it. Does that action even return a value?

Thanks for your help!

DaGbyte
  • 41
  • 4
  • The ExecuteProgram(s) method should return a value of 0 for success nonzero for error (https://learn.microsoft.com/en-us/mem/configmgr/develop/reference/core/clients/sdk/executeprogram-method-in-class-ccm_programsmanager). Any reason you think it should be exitcode? I think the standard return value for a wmi call would be a property called ReturnValue. However if you just call it without specifying any property (or even without assigning it just watching stdout) you should be able to just see what it is really called in your case. – Syberdoor Nov 19 '20 at 14:54