Converting a WMI script to CIM (SCCM 2012 Client)

I want to trigger software updates to install via SCCM 2012 which works fine with WMI but I can’t get the CIM equivalent to work. Hoping someone can help.

WMI that works…

$a = get-wmiobject -query "SELECT * FROM CCM_SoftwareUpdate" -namespace "ROOT\ccm\ClientSDK"
([wmiclass]'ROOT\ccm\ClientSDK:CCM_SoftwareUpdatesManager').InstallUpdates($a)

CIM that does not…

$a = Get-CimInstance -Query "SELECT * FROM CCM_SoftwareUpdate" -Namespace "ROOT\ccm\ClientSDK"
([cimclass]'ROOT\ccm\ClientSDK:CCM_SoftwareUpdatesManager').InstallUpdates($a)
Cannot convert the "CCM_SoftwareUpdate (UpdateID = "Site_xxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx...)" value of type "Microsoft.Management.Infrastructure.CimInstance#ROOT/ccm/ClientSDK/CCM_SoftwareUpdate" to 
type "System.Management.ManagementObject".
At line:1 char:1
+ $a = Get-CimInstance -Query "SELECT * FROM CCM_SoftwareUpdate" -Names ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException
 
Cannot convert the "ROOT\ccm\ClientSDK:CCM_SoftwareUpdatesManager" value of type "System.String" to type "Microsoft.Management.Infrastructure.CimClass".
At line:2 char:1
+ ([cimclass]'ROOT\ccm\ClientSDK:CCM_SoftwareUpdatesManager').InstallUp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException

I don’t know if any of the below helps but figured I would post it since most people won’t have the SCCM 2012 client installed. I’m sort of out of my depth

https://msdn.microsoft.com/en-us/library/jj155391.aspx

PS C:\WINDOWS\system32> Get-CimClass -ClassName CCM_SoftwareUpdatesManager -Namespace "ROOT\ccm\ClientSDK" | select -ExpandProperty Cimclassmethods

Name                              ReturnType Parameters                                  Qualifiers           
----                              ---------- ----------                                  ----------           
InstallUpdates                        UInt32 {CCMUpdates}                                {implemented, static}
CancelDownload                        UInt32 {}                                          {implemented, static}
PostponeUpdatesToNonBusinessHours     UInt32 {CCMUpdates, RebootImmediatelyAfterInstall} {implemented, static}
SetAllUpdatesUserExperience           UInt32 {UserExperience}                            {implemented, static}
GetAllUpdatesUserExperience           UInt32 {UserExperience}                            {implemented, static}

Take a look at this blog: Invoking CIM Methods with PowerShell - Scripting Blog.

Basically, you can’t call methods the same way using CIM, try something like:

$sup = Get-CimInstance -ClassName CCM_SoftwareUpdate -Namespace "ROOT\ccm\ClientSDK";
Invoke-CimMethod -InputObject $sup -MethodName InstallUpdates;

I’ve tried that but just get.

Invoke-CimMethod : Method "InstallUpdates" not found
At line:1 char:1
+ Invoke-CimMethod -InputObject $sup -MethodName InstallUpdates
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (CCM_SoftwareUpd...-F4E3E07E18...):CimInstance) [Invoke-CimMet
   hod], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041002,Microsoft.Management.Infrastructure.CimCmdlets.InvokeCimMet
   hodCommand

I suppose that’s because it’s CCM_SoftwareUpdatesManager rather than CCM_SoftwareUpdate that is used to do the installation.

This looks like it should point you in the right direction. It appears when you do the invoke you have to reference the namespace, etc. to find the method:

Your original code

$a = get-wmiobject -query "SELECT * FROM CCM_SoftwareUpdate" -namespace "ROOT\ccm\ClientSDK"
([wmiclass]'ROOT\ccm\ClientSDK:CCM_SoftwareUpdatesManager').InstallUpdates($a)

can’t be converted directly.

[wmiclass] is a type accelerator for System.management.Class (see page 88 of PowerShell and WMI) and should be used to create new instances of a PowerShell class

There isn’t a [cimclass] type accelerator

You need to invoke the method of the class when using the CIM cmdlets so something like

$sup = Get-CimInstance -ClassName CCM_SoftwareUpdate -Namespace 'ROOT\ccm\ClientSDK'
Invoke-CimMethod -ClassName CCM_SoftwareUpdatesManage -MethodName InstallUpdates -Namespace 'ROOT\ccm\ClientSDK' -Arguments $sup

should work

Thanks for both replying. It looks like I have gone full circle though from when I posted this on Reddit. This should be simple but just doesn’t work.

Invoke-CimMethod : Cannot bind parameter 'Arguments'. Cannot convert the "CCM_SoftwareUpdate (UpdateID = "xxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx...)" value of type 
"Microsoft.Management.Infrastructure.CimInstance#ROOT/ccm/ClientSDK/CCM_SoftwareUpdate" to type "System.Collections.IDictionary".
At line:2 char:125
+ ... odName InstallUpdates -Namespace 'ROOT\ccm\ClientSDK' -Arguments $sup
+                                                                      ~~~~
    + CategoryInfo          : InvalidArgument: (:) [Invoke-CimMethod], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Management.Infrastructure.CimCmdlets.InvokeCimMethodCommand

I tried something like this but it also fails.

$sup = Get-CimInstance -ClassName CCM_SoftwareUpdate -Namespace 'ROOT\ccm\ClientSDK'
$sup | ForEach {
    $Arguments = @{
        ArticleID = $PSItem.ArticleID
        BulletinID = $PSItem.BulletinID
        ComplianceState = $PSItem.ComplianceState
        ContentSize = $PSItem.ContentSize
        Deadline = $PSItem.Deadline
        Description = $PSItem.Description
        ErrorCode = $PSItem.ErrorCode
        EstimatedInstallTime = $PSItem.EstimatedInstallTime
        EvaluationState = $PSItem.EvaluationState
        ExclusiveUpdate = $PSItem.ExclusiveUpdate
        FullName = $PSItem.FullName
        MaxExecutionTime = $PSItem.MaxExecutionTime
        Name = $PSItem.Name
        NextUserScheduledTime = $PSItem.NextUserScheduledTime
        NotifyUser = $PSItem.NotifyUser
        OverrideServiceWindows = $PSItem.OverrideServiceWindows
        Publisher = $PSItem.Publisher
        StartTime = $PSItem.StartTime
        Type = $PSItem.Type
        UpdateID = $PSItem.UpdateID
        URL = $PSItem.URL
        UserUIExperience = $PSItem.UserUIExperience
    } 
    Invoke-CimMethod -ClassName CCM_SoftwareUpdatesManager -MethodName InstallUpdates -Namespace 'ROOT\ccm\ClientSDK' -Arguments $Arguments
}
Invoke-CimMethod : Invalid parameter "ExclusiveUpdate"
At line:26 char:5
+     Invoke-CimMethod -ClassName CCM_SoftwareUpdatesManager -MethodNam ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (ROOT\ccm\Client...eUpdatesManager:String) [Invoke-CimMethod], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041002,Microsoft.Management.Infrastructure.CimCmdlets.InvokeCimMethodCommand

It’s odd but the only parameter it wants is CCMUpdates which is in none of the properties.

(Get-CimClass -ClassName CCM_SoftwareUpdatesManager -Namespace 'ROOT\ccm\ClientSDK').CimClassMethods['InstallUpdates']


Name           ReturnType Parameters   Qualifiers           
----           ---------- ----------   ----------           
InstallUpdates     UInt32 {CCMUpdates} {implemented, static}

Any more ideas from anyone before I consider being beaten? :frowning:

That particular class, if I’m seeing this correctly, is built using a kind of odd underlying provider. I think .NET is having trouble connecting to it properly. Keep in mind that CIM is basically native code, and this particular one doesn’t appear to be entirely complying with the interface standards. Which, given SCCM, perhaps is not shocking.

Thanks Don.
I’ll maybe then have to just resort to wrapping the WMI inside an Invoke-Command as I need to utilise WinRM.