Search code examples
c#sccm

Need help using C# code to execute SCCM Task Sequence


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!!


Solution

  • 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!