将CimInstance数组传递给CimMethod

时间:2015-01-19 08:57:57

标签: powershell wmi

我正在通过Cim cmdlet使用WMI API。问题是我无法弄清楚如何将wmi对象传递给接受wmi对象数组的wmi方法。

以下是方法参数定义:

Name                                            CimType Qualifiers
----                                            ------- ----------
Path                                             String {ID, in}
Permissions                               InstanceArray {EmbeddedInstance, ID, in}
ResetChildren                                   Boolean {ID, in}

PathResetChildren是简单的参数。他们分别接受"/path"$true这样的简单值。但我对Permissions参数感到麻烦。

这是我的代码

#Acquiring object that I want to pass to method
$group = Get-CimInstance -Namespace "root\VisualSVN" -ClassName VisualSVN_Group -Filter "Name='Readers'"

#Acquiring object which method will be called
$repositories = Get-CimInstance -Namespace "root\VisualSVN" -ClassName VisualSVN_Repository

#Preparing method arguments
$args = @{
    Path = "/";
    Permissions = @($group[0]); #Trouble here
    ResetChildren = $true
}

#Invoking method with arguments
Invoke-CimMethod -InputObject ($repositories[0]) -MethodName SetSecurity -Arguments $args

执行此代码将导致错误:

Invoke-CimMethod : Unable to cast object of type 'Microsoft.Management.Infrastructure.CimInstance' to type 'M
icrosoft.Management.Infrastructure.Native.InstanceHandle'.
Parameter name: value
At C:\somepath\script1.ps1:11 char:1
+ Invoke-CimMethod -InputObject ($repositories[0]) -MethodName SetSecurity -Argume ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Invoke-CimMethod], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.Management.Infrastructure.CimCmdlets.Invoke
   CimMethodCommand

如果您更改了代码

Permissions = @($group[0]); #Trouble here

编码

Permissions = $group; #Trouble here

然后错误消息也会改变:

Invoke-CimMethod : Unable to cast object of type 'Microsoft.Management.Infrastructure.Native.InstanceHandle'
to type 'System.Collections.IList'.
Parameter name: value
At C:\somepath\script1.ps1:11 char:1
+ Invoke-CimMethod -InputObject ($repositories[0]) -MethodName SetSecurity -Argume ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Invoke-CimMethod], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.Management.Infrastructure.CimCmdlets.Invoke
   CimMethodCommand

如何正确地将$group传递给方法?

3 个答案:

答案 0 :(得分:1)

我与VisualSVN_Repository::SetSecurity方法存在完全相同的问题。

使用CIM方法参数时,必须将任意数组参数强制转换为 [CimInstance[]]

例如,这对我有用:

$Everyone = Get-CimInstance -Namespace root/VisualSVN -ClassName VisualSVN_Everyone
# Grant Everyone a Read/Write access:
$AccessRule = New-CimInstance -Namespace root/VisualSVN -ClassName VisualSVN_PermissionEntry -ClientOnly -Property @{ Account = $Everyone; AccessLevel = [UInt32]2 }
$SvnRepo = Get-CimInstance -Namespace root/VisualSVN -ClassName VisualSVN_Repository -Filter "Name='MY_REPOSITORY_NAME'"

Invoke-CimMethod -InputObject $SvnRepo -MethodName SetSecurity -Arguments @{ 
    Path = '/';
    Permissions = [CimInstance[]]$AccessRule;
    ResetChildren = $true
} | Out-Null

您必须将数组参数强制转换为[CimInstance[]],即使它只是一个项目。

P.S。:请注意Ref数组参数:首先必须将其转换为[CimInstance[]],然后转换为[ref[]]。例如,在调用VisualSVN_Group::Create方法时:

[CimInstance[]] $SvnUsers = [CimInstance[]]($ArrayOf_VisualSVN_User_Objects)

Invoke-CimMethod -ClassName VisualSVN_Group -Namespace root/VisualSVN -MethodName Create -Arguments @{
    Members = [ref[]]$SvnUsers;
    Name = 'MY_NEW_GROUP_NAME'
} | Out-Null

另请参阅:Tip#5: Passing ref and embedded instances on PowerShell Blog.

答案 1 :(得分:0)

如果你有一个不依赖于我没有安装的软件的repro,我可以肯定地回答,所以我会根据你从你的问题中推断出来做出最好的尝试。

要将您分配给Permissions数组的内容,并且只分配一个值,请在前面使用逗号。

Permissions = ,$group

这是一些示例脚本和要演示的输出。

<强>脚本

$var1 = "any value"
$var2 = ,$var1

$var1.GetType()
$var2.GetType()
$var2.Count
$var2[0]

<强>输出

IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     String    System.Object
True     True     Object[]  System.Array
1
any value

答案 2 :(得分:0)

一个可能的解决方案(它对我来说有一个类似的问题导致我在这里)基于&#39;提示&#39; CIM是惰性物体。在我的情况下,它是以脚本方式安装SCCM更新,同时允许重新启动,如果更新需要它们,并在整个过程花费超过一定时间(不超过可用维护窗口)时停止。

我正在将CIMUpdate对象传递给powershell函数以执行更新,以便在更新之间允许重新启动(一次执行一次更新,验证是否需要重新启动,然后尝试下一次更新)。 p>

CIM对象在强制转换为[CIMInstance[]]时出现类型不匹配错误,如果没有转换,我会得到相同的Unable to cast object of type 'Microsoft.Management.Infrastructure.CimInstance' to type 'Microsoft.Management.Infrastructure.Native.InstanceHandle'错误消息。

解决方案是使用CIMUpdate并重新查询以获取函数中对象的live版本,然后使用该新对象作为CIMMethod的参数。