Tuesday, January 8, 2013

Powershell and WbemScripting Enumerators


I once read that is impossoble to do enumerators in Powershell.  Not true.

The below example uses GetEnumerator:

$Locator = new-Object -comObject "WbemScripting.SWbemLocator"
$svc = $Locator.ConnectServer(".", "root\cimv2")
$ob = $svc.Get("Win32_Process")
$objs = $ob.Instances_(0)

if($objs.Count -gt 0)
{
$mocEnum = $objs.GetEnumerator

$iret = $mocEnum.MoveNext()
do
{
$mo = $mocEnum.Current
$propEnum = $mo.Properties_.GetEnumerator
$ret = $propEnum.MoveNext()
do
{
$prop = $propEnum.Current
[System.String]$s = $prop.Name
write-host $s.PadRight(30, " ") : $prop.Value
}
until($propEnum.MoveNext() -eq $False)
write-host
}
until($mocEnum.MoveNext() -eq $False)
}
else
{
$mo = @($moc)[0]
$propEnum = $mo.GetEnumerator
do
{
$prop = $propEnum.Current
[System.String]$s = $prop.Name
write-host $s.PadRight(30, " ") : $prop.Value
}
until($propEnum.MoveNext() -eq $False)
}


The below example uses reflection and GetEnumerator:

$Locator = new-Object -comObject "WbemScripting.SWbemLocator"
$svc = $Locator.ConnectServer(".", "root\cimv2")
$ob = $svc.Get("Win32_Process")
$objs = $ob.Instances_(0)

if($objs.Count -gt 0)
{
    $mocEnum = $objs.GetType().InvokeMember("GetEnumerator", [System.Reflection.BindingFlags]::InvokeMethod, $Null, $objs, $Null)
    $iret = $mocEnum.MoveNext()   
    do
    {
        $mo = $mocEnum.Current
        $propEnum = $mo.Properties_.GetType().InvokeMember("GetEnumerator", [System.Reflection.BindingFlags]::InvokeMethod, $Null, $mo.Properties_, $Null)
        $ret = $propEnum.MoveNext()
        do
        {
            $prop = $propEnum.Current
            [System.String]$s = $prop.Name
            write-host $s.PadRight(30, " ") : $prop.Value
        }
        until($propEnum.MoveNext() -eq $False)
     write-host
    }
    until($mocEnum.MoveNext() -eq $False)
}
else
{
    $mo = @($moc)[0]
    $propEnum = $mo.Properties.$mo.Properties_.GetType().InvokeMember("GetEnumerator", [System.Reflection.BindingFlags]::InvokeMethod, $Null, $mo.Properties_, $Null)
   do
   {
        $prop = $propEnum.Current
        [System.String]$s = $prop.Name
        write-host $s.PadRight(30, " ") : $prop.Value
   }
   until($propEnum.MoveNext() -eq $False)
}

The below example uses reflection and __NewEnum:

$Locator = new-Object -comObject "WbemScripting.SWbemLocator"
$svc = $Locator.ConnectServer(".", "root\cimv2")
$ob = $svc.Get("Win32_Process")
$objs = $ob.Instances_(0)

if($objs.Count -gt 0)
{
$mocEnum = $objs.GetType().InvokeMember("_NewEnum", [System.Reflection.BindingFlags]::InvokeMethod, $Null, $objs, $Null)
$iret = $mocEnum.MoveNext()
do
{
$mo = $mocEnum.Current
$propEnum = $mo.Properties_.GetType().InvokeMember("_NewEnum", [System.Reflection.BindingFlags]::InvokeMethod, $Null, $mo.Properties_, $Null)
$ret = $propEnum.MoveNext()
do
{
$prop = $propEnum.Current
[System.String]$s = $prop.Name
write-host $s.PadRight(30, " ") : $prop.Value
}
until($propEnum.MoveNext() -eq $False)
write-host
}
until($mocEnum.MoveNext() -eq $False)
}
else
{
$mo = @($moc)[0]
$propEnum = $mo.Properties.$mo.Properties_.GetType().InvokeMember("_NewEnum", [System.Reflection.BindingFlags]::InvokeMethod, $Null, $mo.Properties_, $Null)
do
{
$prop = $propEnum.Current
[System.String]$s = $prop.Name
write-host $s.PadRight(30, " ") : $prop.Value
}
until($propEnum.MoveNext() -eq $False)
}


Hope this helps!  Happy Powershelling!


No comments:

Post a Comment