New-CimInstance cmdlet and the–Key parameter

I was asked a question about the –Key parameter on New-CimInstance today. I wasn’t sure of the answer so I’ve done some experimentation.

I tend to avoid New-CimInstance if I can preferring to use the Create method on the CIM class – however not all CIM classes have a create method so need to fall back on New-CimInstance.

I started by looking at the documentation. The help file for New-CimInstance says:

-Key<String[]>

Specifies the properties that are used as keys. CimSession and ComputerName cannot be used when Key is specified.

That then leads to the question how do I discover the Key or Keys of a CIM class.  You can’t use the –Qualifier parameter in Get-CimClass because that works at the class level and Key is a property qualifier.  Means you need to use some code

function Get-CimClassKey { 

    param (
   
        [string]$CIMnamespace = ‘ROOT/cimv2’,
       
        [string]$CIMclass
   
    )

    $class = Get-CimClass -Namespace $CIMnamespace -ClassName $CIMclass

    foreach ($property in $class.CimClassProperties) {
 
        $property | Select-Object -ExpandProperty Qualifiers |
        foreach {
            if ($_.Name -eq ‘key’){
                $property
            }
        }

    }
}

The Key property of a class HAS to be given a value when a new instance of the class is created.

The New-CimInstance help file shows an example using Win32_Environment.  Adapring the example:

PS> New-CimInstance -ClassName Win32_Environment @{Name=’RStest1′; VariableValue=’test1′; UserName=’RSSURFACEPRO2\Richard’}

Name             UserName                                            VariableValue
—-             ——–                                            ————-
RStest1          RSSURFACEPRO2\Richard                               test1

Using our function to discover the Keys of Win32_Environment

PS> Get-CimClassKey -CIMclass Win32_Environment

Name               : Name
Value              :
CimType            : String
Flags              : Property, Key, NullValue
Qualifiers         : {read, key, MappingStrings, Override…}
ReferenceClassName :

Name               : UserName
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {key, MappingStrings, MaxLen, read}
ReferenceClassName :

Adding the –Key parameter

PS> New-CimInstance -ClassName Win32_Environment @{Name=’RStest2′; VariableValue=’test2′; UserName=’RSSURFACEPRO2\Richard’} -Key ‘Name’, ‘UserName’

Name             UserName                                            VariableValue
—-             ——–                                            ————-
RStest2          RSSURFACEPRO2\Richard                               test2

Using Win32_Environment you can use the Key parameter, or not, as long as you define values for the Name and Username properties.

Another example in the New-CimInstance help file uses the Win32_Process class.  The key for that class is the Handle property

PS> Get-CimClassKey -CIMclass Win32_process

Name               : Handle
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {key, MaxLen, read}
ReferenceClassName :

the Handle is appears to be identical to the ProcessId in value as far as I can determine

This now gets  messy:

Just the Handle.  BTW exmple 3 in the documentation has an error as Handle is a string not an integer

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′}
New-CimInstance : Provider is not capable of the attempted operation
At line:1 char:1
+ New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Win32_Process:CimInstance) [New-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041024,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

Add the Key parameter

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -Key Handle
New-CimInstance : Provider is not capable of the attempted operation
At line:1 char:1
+ New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -Key …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Win32_Process (Handle = “0”):CimInstance) [New-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041024,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

The only way it works is if you use –ClientOnly to make an in memory CIM instance that only exists in your PowerShell session

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -Key Handle -ClientOnly

Handle PSComputerName
—— ————–
0

You can remove the –Key parameter

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -ClientOnly

Handle PSComputerName
—— ————–
0

Win32_Process has a Create method that takes these parameters

PS> $class.CimClassMethods[‘Create’].Parameters

Name                       CimType Qualifiers                                 ReferenceClassName
—-                                 ——- ———-                                 ——————
CommandLine                 String {ID, In, MappingStrings}
CurrentDirectory            String {ID, In, MappingStrings}
ProcessStartupInformation Instance {EmbeddedInstance, ID, In, MappingStrings}
ProcessId                   UInt32 {ID, MappingStrings, Out}

Using Invoke-CimMethod

PS> Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine=’notepad.exe’}

ProcessId ReturnValue PSComputerName
——— ———– ————–
     2648           0

Now trying New-CimInstance

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′; CommandLine=’notepad.exe’} -Key Handle
New-CimInstance : Provider is not capable of the attempted operation
At line:1 char:1
+ New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′; Comm …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Win32_Process (Handle = “0”):CimInstance) [New-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041024,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

Other variants of not including the Handle property and changing the handle value all fail with same error

Botton line is that New-CimInstance is a bit of a mess to use – with or without the –Key parameter (which doesn’t seem to do much).

If the CIM class hasa create method Id recommend that you use that as a lot of CIm classes (or their providers) don’t work with New-cimInstance. In reality given that many of the CIM classes are effectively read only – you can’t create a new instance of Win32_ComputerSystem for example – it probably doesn’t matter.

This entry was posted in CIM, PowerShell and CIM, PowerShell and WMI. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s