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.
The post New-CimInstance cmdlet and the–Key parameter appeared first on PowerShell for Windows Admins.