2015-01-19 2 views
5

Я работаю с API WMI с помощью командлетов Cim. Проблема в том, что я не могу понять, как передать объект wmi на wmi-метод, который принимает массив объектов wmi.Пропустить массив CimInstance до CimMethod

Вот метод определения параметров:

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 на метод правильно?

+0

у меня нет VisualSVN установлен, поэтому не может проверить это, но делает ваш «$ группа [0]» объект есть Обработать свойство? Если да, то как насчет передачи «$ group [0] .Handle»? –

+0

Я думаю, что эта проблема не связана непосредственно с VisualSVN. Таким образом, вы можете воспроизвести его любым методом WMI, который имеет аналогичную подпись. Метод должен принимать массив некоторых объектов WMI. К сожалению, моя «$ group [0]» не имеет ни свойства Handle, ни чего-то, что связано с InstanceHandle. Класс InstanceHandle связан с деталями внутренней реализации и не имеет публичной документации. Я предполагаю, что это исключение бросает, когда PowerShell делает магию для преобразования из внутреннего представления объекта WMS PowerShell в чистый объект WMI. – rotor

+0

Я понимаю, что это не проблема VisualSVN, было бы неплохо воспроизвести ошибку. Вот еще один пример [link] http://powershell.com/cs/forums/p/13888/26108.aspx. К сожалению, я тоже не могу воспроизвести его. Один «намек», который я нашел, - «Командлеты CIM возвращают инертные объекты» ([link] http://blogs.msmvps.com/richardsiddaway/category/powershellandwmi/page/4/) В нем объясняется, что объекты, Сопротивление - это «инертные» копии объектов WMI без каких-либо методов. Я попытался бы переписать код с помощью Get-WmiObject и посмотреть, можете ли вы вызвать метод напрямую. –

ответ

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.

0

Если у вас был репродуктор, который не полагался на программное обеспечение, которое я не установил, я мог бы ответить окончательно, поэтому сделаю все возможное, исходя из того, что я могу сделать из вашего вопроса.

Чтобы сделать то, что вы присваиваете Permissions массиву, и вы назначаете только одно значение, используйте запятую спереди.

Permissions = ,$group

Ниже приведен пример сценария и выход для демонстрации.

Script

$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 
0

Возможное решение (он работал для меня с подобным вопросом, который привел меня сюда), основанный на 'намек', что CIM являются инертных объектов. В моем случае он устанавливал обновления SCCM сценарием, позволяя перезагружать, если обновления требовали их, и останавливался, если весь процесс занял больше определенного времени (чтобы не пройти через доступное окно обслуживания).

Я передавал объект CIMUpdate с помощью функции powershell для выполнения обновления, позволяющего при необходимости перезагружать обновления (одновременно выполняйте одно обновление, проверяйте необходимость перезагрузки, затем попробуйте следующее обновление).

Объект CIM выдавал ошибку несоответствия типа, заставляя его отличать как [CIMInstance[]], и, если бы не литье вообще, я бы получил то же сообщение об ошибке Unable to cast object of type 'Microsoft.Management.Infrastructure.CimInstance' to type 'Microsoft.Management.Infrastructure.Native.InstanceHandle'.

Решение должно было использовать этот CIMUpdate и повторно запросить, чтобы получить live вариант объекта внутри функции, а затем использовать этот новый объект в качестве аргумента для CIMMethod.

Смежные вопросы