将 CimInstance 数组传递给 CimMethod
Pass array of CimInstance to CimMethod
我正在通过 Cim cmdlet 使用 WMI API。问题是我不知道如何将 wmi 对象传递给接受 wmi 对象数组的 wmi 方法。
方法参数定义如下:
Name CimType Qualifiers
---- ------- ----------
Path String {ID, in}
Permissions InstanceArray {EmbeddedInstance, ID, in}
ResetChildren Boolean {ID, in}
Path
和 ResetChildren
是简单的参数。它们分别接受像 "/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
正确传递给方法有什么想法吗?
如果你有一个不依赖于我没有安装的软件的重现,我可以肯定地回答,所以我会根据我从你的问题中推断出的内容做出我最好的尝试。
要使您分配给 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
基于 CIM 是惰性对象的 'hint' 的可能解决方案(它对我有类似的问题,导致我来到这里)。在我的例子中,它以脚本方式安装 SCCM 更新,同时允许在更新需要时重新启动,并在整个过程花费超过一定时间时停止(不超过可用维护 window) .
我将 CIMUpdate 对象传递给 powershell 函数以执行更新,以便在更新之间必要时重新启动(一次执行一个更新,验证是否需要重新启动,然后尝试下一个更新)。
CIM 对象在强制转换为 [CIMInstance[]]
时出现类型不匹配错误,如果根本不转换,我会收到相同的 Unable to cast object of type 'Microsoft.Management.Infrastructure.CimInstance' to type 'Microsoft.Management.Infrastructure.Native.InstanceHandle'
错误消息。
解决方案是使用 CIMUpdate
并重新查询以在函数中获取对象的 live
版本,然后使用该新对象作为 CIMMethod 的参数。
我在使用 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.
截至目前,它适用于我,我正在处理的案例是将 New-ScheduledTaskTrigger
实例传递给函数。
我正在将 CimInstance
传递给一个函数并接收它作为 PSCustomObject
类型。
- 发送
CimInstance
作为 [PSCustomObject] 接收 -> 在目标处它仍然是 CimInstance
对象类型
- 发送
CimInstance
作为 [CimInstance] 接收 -> 在目标处它仍然是 CimInstance
对象类型
- 发送
CimInstance
作为 [CimInstance[]] 接收 -> 在目标处它变成 CimInstance
数组类型
我正在通过 Cim cmdlet 使用 WMI API。问题是我不知道如何将 wmi 对象传递给接受 wmi 对象数组的 wmi 方法。
方法参数定义如下:
Name CimType Qualifiers
---- ------- ----------
Path String {ID, in}
Permissions InstanceArray {EmbeddedInstance, ID, in}
ResetChildren Boolean {ID, in}
Path
和 ResetChildren
是简单的参数。它们分别接受像 "/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
正确传递给方法有什么想法吗?
如果你有一个不依赖于我没有安装的软件的重现,我可以肯定地回答,所以我会根据我从你的问题中推断出的内容做出我最好的尝试。
要使您分配给 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
基于 CIM 是惰性对象的 'hint' 的可能解决方案(它对我有类似的问题,导致我来到这里)。在我的例子中,它以脚本方式安装 SCCM 更新,同时允许在更新需要时重新启动,并在整个过程花费超过一定时间时停止(不超过可用维护 window) .
我将 CIMUpdate 对象传递给 powershell 函数以执行更新,以便在更新之间必要时重新启动(一次执行一个更新,验证是否需要重新启动,然后尝试下一个更新)。
CIM 对象在强制转换为 [CIMInstance[]]
时出现类型不匹配错误,如果根本不转换,我会收到相同的 Unable to cast object of type 'Microsoft.Management.Infrastructure.CimInstance' to type 'Microsoft.Management.Infrastructure.Native.InstanceHandle'
错误消息。
解决方案是使用 CIMUpdate
并重新查询以在函数中获取对象的 live
版本,然后使用该新对象作为 CIMMethod 的参数。
我在使用 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.
截至目前,它适用于我,我正在处理的案例是将 New-ScheduledTaskTrigger
实例传递给函数。
我正在将 CimInstance
传递给一个函数并接收它作为 PSCustomObject
类型。
- 发送
CimInstance
作为 [PSCustomObject] 接收 -> 在目标处它仍然是CimInstance
对象类型 - 发送
CimInstance
作为 [CimInstance] 接收 -> 在目标处它仍然是CimInstance
对象类型 - 发送
CimInstance
作为 [CimInstance[]] 接收 -> 在目标处它变成CimInstance
数组类型