6

I'd like to start at the top of a WMI namespace, recurse through all the objects, then recurse through each object's property list, filtering out and returning to console only those properties that have mem in their names.

This is what I have so far:

gwmi -namespace "root\cimv2" -list |???? |get-Member -MemberType property | Where-Object { $_.name -match 'mem'}

Notice the big |???? in the middle there. If I remove that, the the command seems to run, but fails to find properties I know should be found. Why? I think it is because I get different output from the following two commands:

gwmi "Win32_operatingSystem"  |get-Member -MemberType property (73 lines of output)
gwmi -namespace "root\cimv2" -list  |where-object { $_.Name -eq 'Win32_OperatingSystem' } |get-Member -MemberType property (10 lines of output)

What I want is a one-liner that recursively concatenates this process:

gwmi -namespace "root\cimv2" -list
(manual selection of a WMI class from the list of 1000+ which appear) 
gwmi "win32_OperatingSystem" | get-Member -MemberType property | Where-Object { $_.Definition -match 'mem' }

Thanks, and if a working answer is given, I will accept and upvote it (annoying when people never do that, isn't it?).

Note added 2009/11/14: I haven't awarded the answer yet because no one has yet provided a one-liner which solves the problem.

quux
  • 5,358
  • 1
  • 23
  • 36
  • Why do you need a one-liner? Just take one of the answers that works and make a function out of it. Then just pass in the parameter for namespace & search term. You'll end up with: _Run-MyFunction_ _namespace_ _searchterm_, which is a lot easier to run from the command line than even a one-liner. – Joe Internet Nov 30 '09 at 19:44
  • 1
    I need to be able to deliver a troubleshooting step over the phone or IM, with a minimum of hassle. – quux Nov 30 '09 at 21:01

5 Answers5

7

I think this will do what you are looking for in one line. the CIMV2 namespace is there by default but if you wanted to select a different one, you can use gwmi -namesapce.

The "trick" is nesting a where-object in side the foreach-object

gwmi -list | % {$_.Properties | ? {$_.Name.Contains('Memory')}} | select Origin,Name
Andy Schneider
  • 1,533
  • 5
  • 19
  • 28
  • 1
    Oh, man. This is *precisely* the answer I was looking for, but I haven't been on serverfault in the past two weeks, and the bounty period has expired. Also there seems no way I can reinstate the bounty and give you the points (I think I was offering 250 points?).Not only that, I can no longer mark this or any other submission as the answer. Andy, I am really sorry about this. Wish I had some way to make it right. – quux Dec 15 '09 at 08:49
  • @quux - no worries, I appreciate the note. I'm just glad you got what you were looknig for. – Andy Schneider Dec 15 '09 at 16:53
2

It looks like that this:

gwmi -namespace "root\cimv2" -list

returns an array of ManagementClass .Net objects, so you can use ManagementClass.Properties collection to select properties that have a certain string in their names. Here is my PowerShell script:

foreach($class in gwmi -namespace "root\cimv2" -list)
{
    foreach($property in $class.Properties)
    {
        if($property.Name.Contains('Memory'))
        {
            $class.Name  + ' --- ' + $property.Name
        }
    }
}

As you can see I am a PowerShell beginner, but I think you can make a 'one-liner' from that.

  • This definitely returns what I was looking for. I'm very much a PS beginner as well, so I am noodling with it to see how I would create the one-liner. Thanks! – quux Sep 04 '09 at 01:24
1

I think by listing the namespace you get WMI CLASS Objects, but not the actual object instances - which you get by gwmi "win32_OperatingSystem" If you use gm you will see:

TypeName: System.Management.ManagementClass#ROOT\cimv2\Win32_OperatingSystem vs TypeName: System.Management.ManagementObject#root\cimv2\Win32_OperatingSystem

edit: You could do something like this:

gwmi -namespace "root\cimv2" -list | %{ gwmi -class $_.name.tostring()}

and if you want all properties with mem* then you could try | select-object "mem*"

but I'm not sure if that is really what you want. I think this is very ineffective if you just need to know the amount of memory. What do you really want to have as output?

Roman
  • 21
  • 1
  • 5
1

It's a little late here, but i'm pretty sure the below will get you to where you are looking to get - that is a listing of all the properties in the WMI namespace that have "mem" in thier name

foreach ($i in gwmi -namespace "root\cimv2" -list ){$i.properties | where-object {$_.name -match 'mem'}| format-table origin,name}
Zypher
  • 36,995
  • 5
  • 52
  • 95
  • This is a correct answer, but I liked the output formatting and simplicity of Andy's answer better. Thank you! – quux Dec 15 '09 at 08:51
-1

Download Microsoft's Scriptomatic2 and PowershellScriptomatic. They're both hta apps, so you can view them as plain text to see how they do it.

gWaldo
  • 11,887
  • 8
  • 41
  • 68
  • Thank you, but no. I have used both, they are fine for enumerating properties of a single WMI object, but no good for more complex scenarios like this one. – quux Sep 24 '11 at 22:59
  • My point is that the apps both apps demonstrate how to iterate over all of the CIM namespaces and all objects (and properties) within each. Perhaps I wasn't clear; I didn't mean for you to run the apps, but rather open them in a text editor and browse the source. – gWaldo Sep 25 '11 at 00:08