@@ -35,6 +35,53 @@ function Get-DscResourceObject {
35
35
return $desiredState
36
36
}
37
37
38
+ function GetWmiInstance {
39
+ [CmdletBinding ()]
40
+ param
41
+ (
42
+ [Parameter (Mandatory = $true , ValueFromPipeline = $true )]
43
+ [psobject ]$DesiredState
44
+ )
45
+
46
+ $type_fields = $DesiredState.type -split " /"
47
+ $wmi_namespace = $type_fields [0 ].Replace(' .' , ' \' )
48
+ $wmi_classname = $type_fields [1 ]
49
+
50
+ if ($DesiredState.properties ) {
51
+ $props = $DesiredState.properties.psobject.Properties | Where-Object { $_.Name -notin @ (' methodName' , ' parameters' ) }
52
+ $query = " SELECT $ ( $props.Name -join ' ,' ) FROM $wmi_classname "
53
+ $where = " WHERE "
54
+ $useWhere = $false
55
+ $first = $true
56
+ foreach ($property in $props ) {
57
+ # TODO: validate property against the CIM class to give better error message
58
+ if ($null -ne $property.value ) {
59
+ $useWhere = $true
60
+ if ($first ) {
61
+ $first = $false
62
+ } else {
63
+ $where += " AND "
64
+ }
65
+
66
+ if ($property.TypeNameOfValue -eq " System.String" ) {
67
+ $where += " $ ( $property.Name ) = '$ ( $property.Value ) '"
68
+ } else {
69
+ $where += " $ ( $property.Name ) = $ ( $property.Value ) "
70
+ }
71
+ }
72
+ }
73
+ if ($useWhere ) {
74
+ $query += $where
75
+ }
76
+ " Query: $query " | Write-DscTrace - Operation Debug
77
+ $wmi_instances = Get-CimInstance - Namespace $wmi_namespace - Query $query - ErrorAction Stop
78
+ } else {
79
+ $wmi_instances = Get-CimInstance - Namespace $wmi_namespace - ClassName $wmi_classname - ErrorAction Stop
80
+ }
81
+
82
+ return $wmi_instances
83
+ }
84
+
38
85
function GetCimSpace {
39
86
[CmdletBinding ()]
40
87
param
@@ -58,43 +105,10 @@ function GetCimSpace {
58
105
59
106
foreach ($r in $DesiredState ) {
60
107
61
- $type_fields = $r.type -split " /"
62
- $wmi_namespace = $type_fields [0 ].Replace(' .' , ' \' )
63
- $wmi_classname = $type_fields [1 ]
64
-
65
108
switch ($Operation ) {
66
109
' Get' {
67
110
# TODO: identify key properties and add WHERE clause to the query
68
- if ($r.properties ) {
69
- $query = " SELECT $ ( $r.properties.psobject.properties.name -join ' ,' ) FROM $wmi_classname "
70
- $where = " WHERE "
71
- $useWhere = $false
72
- $first = $true
73
- foreach ($property in $r.properties.psobject.properties ) {
74
- # TODO: validate property against the CIM class to give better error message
75
- if ($null -ne $property.value ) {
76
- $useWhere = $true
77
- if ($first ) {
78
- $first = $false
79
- } else {
80
- $where += " AND "
81
- }
82
-
83
- if ($property.TypeNameOfValue -eq " System.String" ) {
84
- $where += " $ ( $property.Name ) = '$ ( $property.Value ) '"
85
- } else {
86
- $where += " $ ( $property.Name ) = $ ( $property.Value ) "
87
- }
88
- }
89
- }
90
- if ($useWhere ) {
91
- $query += $where
92
- }
93
- " Query: $query " | Write-DscTrace - Operation Debug
94
- $wmi_instances = Get-CimInstance - Namespace $wmi_namespace - Query $query - ErrorAction Stop
95
- } else {
96
- $wmi_instances = Get-CimInstance - Namespace $wmi_namespace - ClassName $wmi_classname - ErrorAction Stop
97
- }
111
+ $wmi_instances = GetWmiInstance - DesiredState $DesiredState
98
112
99
113
if ($wmi_instances ) {
100
114
$instance_result = [ordered ]@ {}
@@ -119,8 +133,14 @@ function GetCimSpace {
119
133
120
134
}
121
135
' Set' {
122
- # TODO: implement set
136
+ $wmi_instance = ValidateCimMethodAndArguments - DesiredState $r
137
+ InvokeCimMethod - CimInstance $wmi_instance.CimInstance - MethodName $wmi_instance.MethodName - Arguments $wmi_instance.Parameters
123
138
139
+ $result += [PSCustomObject ]@ {
140
+ name = $r.name
141
+ type = $r.type
142
+ properties = $null # Set operation does not return properties
143
+ }
124
144
}
125
145
' Test' {
126
146
# TODO: implement test
@@ -140,7 +160,7 @@ function ValidateCimMethodAndArguments {
140
160
141
161
$methodName = $DesiredState.properties.psobject.properties | Where-Object - Property Name -EQ ' methodName' | Select-Object - ExpandProperty Value
142
162
if (-not $methodName ) {
143
- " 'methodName' property is required for invoking a WMI method." | Write-DscTrace - Operation Error
163
+ " 'methodName' property is required for invoking a WMI/CIM method." | Write-DscTrace - Operation Error
144
164
exit 1
145
165
}
146
166
@@ -149,16 +169,125 @@ function ValidateCimMethodAndArguments {
149
169
150
170
$cimClass = Get-CimClass - Namespace $namespace - ClassName $className - MethodName $methodName
151
171
172
+ $arguments = @ {}
152
173
if ($cimClass ) {
153
- $properties = $DesiredState.properties.psobject.properties | Where-Object - Property Name -NE ' methodName'
154
- $parameters = $cimClass.CimClassMethods | Where-Object - Property Name -EQ $methodName | Select-Object - ExpandProperty CimMethodParameters
174
+ $parameters = ($DesiredState.properties.psobject.properties | Where-Object - Property Name -EQ ' parameters' ).Value
175
+ $cimClassParameters = $cimClass.CimClassMethods | Where-Object - Property Name -EQ $methodName | Select-Object - ExpandProperty Parameters
176
+
177
+ foreach ($param in $parameters.psobject.Properties.name ) {
178
+ if ($cimClassParameters.Name -notcontains $param ) {
179
+ " '$param ' is not a valid parameter for method '$methodName ' in class '$className '." | Write-DscTrace - Operation Warn
180
+ } else {
181
+ $arguments += @ {
182
+ $param = $parameters .$param
183
+ }
184
+ }
185
+ }
186
+
187
+ $cimInstance = GetWmiInstance - DesiredState $DesiredState
155
188
156
- foreach ($prop in $properties ) {
157
-
189
+ $i = [PSCustomObject ]@ {
190
+ CimInstance = $cimInstance
191
+ Parameters = $arguments
192
+ MethodName = $methodName
158
193
}
159
194
}
160
195
161
- return $cimClass
196
+ return $i
197
+ }
198
+
199
+ function InvokeCimMethod
200
+ {
201
+ [CmdletBinding ()]
202
+ [OutputType ([Microsoft.Management.Infrastructure.CimMethodResult ])]
203
+ param
204
+ (
205
+
206
+ [Parameter (Mandatory = $true )]
207
+ [Microsoft.Management.Infrastructure.CimInstance ]
208
+ $CimInstance ,
209
+
210
+ [Parameter (Mandatory = $true )]
211
+ [System.String ]
212
+ $MethodName ,
213
+
214
+ [Parameter ()]
215
+ [System.Collections.Hashtable ]
216
+ $Arguments
217
+ )
218
+
219
+ $invokeCimMethodParameters = @ {
220
+ MethodName = $MethodName
221
+ ErrorAction = ' Stop'
222
+ }
223
+
224
+ if ($PSBoundParameters.ContainsKey (' Arguments' ) -and $null -ne [string ]::IsNullOrEmpty($Arguments ))
225
+ {
226
+ $invokeCimMethodParameters [' Arguments' ] = $Arguments
227
+ }
228
+
229
+ try
230
+ {
231
+ $invokeCimMethodResult = $CimInstance | Invoke-CimMethod @invokeCimMethodParameters
232
+ }
233
+ catch [Microsoft.Management.Infrastructure.CimException ]
234
+ {
235
+ $errMsg = $_.Exception.Message.Trim (" " )
236
+ if ($errMsg -eq ' Invalid method' )
237
+ {
238
+ " Retrying without instance" | Write-DscTrace - Operation Trace
239
+ $invokeCimMethodResult = Invoke-CimMethod @invokeCimMethodParameters - ClassName $CimInstance [0 ].CimClass.CimClassName
240
+ }
241
+ }
242
+ catch
243
+ {
244
+ " Could not execute 'Invoke-CimMethod' with error message: " + $_.Exception.Message | Write-DscTrace - Operation Error
245
+ exit 1
246
+ }
247
+
248
+ <#
249
+ Successfully calling the method returns $invokeCimMethodResult.HRESULT -eq 0.
250
+ If an general error occur in the Invoke-CimMethod, like calling a method
251
+ that does not exist, returns $null in $invokeCimMethodResult.
252
+ #>
253
+ if ($invokeCimMethodResult.HRESULT )
254
+ {
255
+ $res = $invokeCimMethodResult.HRESULT
256
+ }
257
+ else
258
+ {
259
+ $res = $invokeCimMethodResult.ReturnValue
260
+ }
261
+ if ($invokeCimMethodResult -and $res -ne 0 )
262
+ {
263
+ if ($invokeCimMethodResult | Get-Member - Name ' ExtendedErrors' )
264
+ {
265
+ <#
266
+ The returned object property ExtendedErrors is an array
267
+ so that needs to be concatenated.
268
+ #>
269
+ $errorMessage = $invokeCimMethodResult.ExtendedErrors -join ' ;'
270
+ }
271
+ else
272
+ {
273
+ $errorMessage = $invokeCimMethodResult.Error
274
+ }
275
+
276
+ $hResult = $invokeCimMethodResult.ReturnValue
277
+
278
+ if ($invokeCimMethodResult.HRESULT )
279
+ {
280
+ $hResult = $invokeCimMethodResult.HRESULT
281
+ }
282
+
283
+ $errmsg = ' Method {0}() failed with an error. Error: {1} (HRESULT:{2})' -f @ (
284
+ $MethodName
285
+ $errorMessage
286
+ $hResult
287
+ )
288
+ $errMsg | Write-DscTrace - Operation Error
289
+ exit 1
290
+ }
162
291
}
163
292
164
293
@@ -176,17 +305,7 @@ function Invoke-DscWmi {
176
305
$DesiredState
177
306
)
178
307
179
- switch ($Operation ) {
180
- ' Get' {
181
- $addToActualState = GetCimSpace - Operation $Operation - DesiredState $DesiredState
182
- }
183
- ' Set' {
184
- # TODO: Implement Set operation
185
- }
186
- ' Test' {
187
- # TODO: Implement Test operation
188
- }
189
- }
308
+ $addToActualState = GetCimSpace - Operation $Operation - DesiredState $DesiredState
190
309
191
310
return $addToActualState
192
311
}
@@ -195,12 +314,4 @@ class dscResourceObject {
195
314
[string ] $name
196
315
[string ] $type
197
316
[PSCustomObject ] $properties
198
- }
199
-
200
- $inputObject = [DscResourceObject ]@ {
201
- name = ' root.cimv2/Win32_Process'
202
- type = ' root.cimv2/Win32_Process'
203
- properties = [PSCustomObject ]@ {
204
- methodName = ' Create'
205
- }
206
317
}
0 commit comments