3

The code I am writing is suppose to kick off any patches currently available to a server using CIM. And I have to use CIM due to the required DCOM protocol for my network.

I'm using ` for easier viewing

The following wmi code works:

$ComputerName = 'Foo'
[System.Management.ManagementObject[]] $CMMissingUpdates = @(`
    Get-WmiObject -ComputerName $ComputerName `
                  -Query "SELECT * FROM CCM_SoftwareUpdate WHERE ComplianceState = '0'" `
                  -Namespace "ROOT\ccm\ClientSDK" `
                  -ErrorAction Stop)
$null = (Get-WmiObject -ComputerName $ComputerName `
                       -Namespace "root\ccm\ClientSDK" `
                       -Class "CCM_SoftwareUpdatesManager" `
                       -List).InstallUpdates($CMMissingUpdates)

What I've made using CIM that doesn't work:

$null = (Invoke-CimMethod -CimSession $Computer.CimSession `
                          -Namespace 'ROOT\ccm\ClientSDK' `
                          -ClassName 'CCM_SoftwareUpdatesManager' `
                          -MethodName 'InstallUpdates').InstallUpdates($CMMissingUpdates)

Not only am I interested in a solution to my Invoke-CimMethod but how it was solved. I can't seem to determine how to view and implement the methods of classes in CIM.

Keith
  • 689
  • 10
  • 27
  • I'd suggest looking at [`about_Splatting`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-5.1) – Maximilian Burszley Jul 17 '18 at 20:33

2 Answers2

1

Your problem is you're using two incompatible commands to translate.

Invoke-CimMethod == Invoke-WmiMethod

Get-WmiObject is not the above, however. Here's a way to accomplish what you're doing:

$ComputerName = 'Foo'
$cimArgs = @{
    'Namespace'    = 'Root\CCM\ClientSDK'
    'ClassName'    = 'CCM_SoftwareUpdatesManager'
    'MethodName'   = 'InstallUpdates' # returns UInt32 object; 0 = success
    'Arguments'    = @{
        'CCMUpdates' = Get-WmiObject -Namespace Root\CCM\ClientSDK -Class CCM_SoftwareUpdate -Filter 'ComplianceState = "0"'
    }
    'CimSession'   = New-CimSession -ComputerName $ComputerName -SessionOption (New-CimSessionOption -Protocol Dcom)
}
Invoke-CimMethod @cimArgs

The Invoke-CimMethod cmdlet takes a dictionary to pass arguments to the method. I determined the keys/values based on this documentation.

This can alternatively be found by the following:

Get-CimClass -ClassName 'CCM_SoftwareUpdatesManager' -Namespace 'Root\CCM\ClientSDK' |
     ForEach-Object -MemberName CimClassMethods
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • When I use your code I get the following error. `Invoke-CimMethod : Could not infer CimType from the provided .NET object. At line:1 char:1 + Invoke-CimMethod @cimArgs + ~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Invoke-CimMethod], ArgumentException + FullyQualifiedErrorId : System.ArgumentException,Microsoft.Management.Infrastru cture.CimCmdlets.InvokeCimMethodCommand` @TheIncorrigible1 – Keith Jul 18 '18 at 13:43
  • Also, all I am attempting to do is kick off the SCCM "Install All" patches that are currently listed as available on the SCCM Client. – Keith Jul 18 '18 at 14:00
  • @Keith According to the error message, it's a type issue. The method expects `CCM_SoftwareUpdate`. Your type-casting is unnecessary with `[ManagementObject]` – Maximilian Burszley Jul 18 '18 at 14:50
  • @TheIncorrigble1 When I test it without the type-casting, I get the same error. I just want to be able to kick off the installation of any SCCM patches currently listed in the SCCM Client on the computer using CIM. Perhaps `invoke-cimmethod` is not the correct approach. Do you know an an alternative that would illicit the result I'm trying to achieve? – Keith Jul 18 '18 at 15:00
  • You can use `Get-CimInstance` which is equivalent to `Get-WmiObject` (for the most part). I'll update my answer using this method. – Maximilian Burszley Jul 18 '18 at 15:10
0

Turns out it was a casting issue. Link to solution: https://www.reddit.com/r/PowerShell/comments/8zvsd8/kick_off_a_sccm_clients_install_all_available/

The final solution:

$CMMissingUpdates = @( `
  Get-CimInstance -Query "SELECT * FROM CCM_SoftwareUpdate WHERE ComplianceState = '0'" `
                  -Namespace "ROOT\ccm\ClientSDK"
)
Invoke-CimMethod -Namespace 'ROOT\ccm\ClientSDK' `
                 -ClassName 'CCM_SoftwareUpdatesManager' `
                 -MethodName 'InstallUpdates' `
                 -Arguments @{ 
                    CCMUpdates = [cminstance[]]$CMMissingUpdates
                 }
Keith
  • 689
  • 10
  • 27