JScript Enumerator and list of properties
Asked Answered
H

3

6

Consider the following WSH snippet:

var query = GetObject("winmgmts:").ExecQuery("SELECT Name FROM Win32_Printer", "WQL", 0);
var e = new Enumerator(query);
for ( ; !e.atEnd(); e.moveNext ()) { 
    var p = e.item();
    WScript.Echo(p.Name + " (" + p.Status + ")");
}

It prints in every line a printer name and the word "undefined" in brackets (because Status property isn't exist in p object). The question is: how can I list all available properties from p? The usual technique with for (var i in p) {...} doesn't work--it seems that properties in p object aren't enumerable.

Thanks in advance.

Heatstroke answered 9/6, 2009 at 23:29 Comment(0)
E
10

JScript's for...in statement isn't compatible with WMI objects, because, well, they are more complex than native JScript objects. WMI objects expose their property collection via the special Properties_ property, so to list all available properties of an object, you need to enumerate this collection like you enumerate the query results to access individual WMI objects. Each object property is represented by a SWbemProperty object that has the Name, Value and other properties providing info about the appropriate object property.

This example should help you get the idea:

var query = GetObject("winmgmts:").ExecQuery("SELECT Name, Status FROM Win32_Printer");
var colPrinters = new Enumerator(query);

var oPrinter, colProps, p;

// Enumerate WMI objects
for ( ; !colPrinters.atEnd(); colPrinters.moveNext()) { 
    oPrinter = colPrinters.item();

    // Enumerate WMI object properties
    colProps = new Enumerator(oPrinter.Properties_);
    for ( ; !colProps.atEnd(); colProps.moveNext()) { 
        p = colProps.item();
        WScript.Echo(p.Name + ": " + p.Value);
    }
}

Note that this script will also display the DeviceID property value, because it's a key property of the Win32_Printer class, so it's also retrieved in order to uniquely identify class instances.

Emlyn answered 10/6, 2009 at 7:22 Comment(1)
@HenryFlower As much as I like those cyrillic letters it's best to write in English here :) By the way, I wouldn't think a "Henry Flower" would be from Russia!Glarum
V
6

If you'd like to avoid the need to use an explicit Enumerator every time you need to iterate over a collection object that needs one, you can define a little helper function like this:

function forEach(collection, func) {
 for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
  func(e.item());
 }
}

Iteration over collections then becomes rather less clumsy:

var queryResult = GetObject("winmgmts:").ExecQuery("SELECT Name, Status FROM Win32_Printer");

// Enumerate WMI objects
forEach (queryResult, function (oPrinter) {

    // Enumerate WMI object properties
    forEach (oPrinter.Properties_, function (p) {
        WScript.Echo(p.Name + ": " + p.Value);
    });
});
Ventriloquize answered 16/11, 2010 at 6:59 Comment(1)
Since you can't directly break out of the loop from within the callback function, it might be a good idea to include a return value condition check in the loop, such as if(func(e.item()) === false) break;, allowing you to return false from within the callback when you need to break outRiches
T
1

I think the problem is in your query you're only asking for the Name. Try asking for both Name and status:

var query = GetObject("winmgmts:").ExecQuery("SELECT Name, Status  FROM Win32_Printer", "WQL", 0);
var e = new Enumerator(query);
for ( ; !e.atEnd(); e.moveNext ()) { 
    var p = e.item();
    WScript.Echo(p.Name + " (" + p.Status + ")" );
}

I got some more properties from http://msdn.microsoft.com/en-us/library/aa394363(VS.85).aspx and several work. I queried for DriverName and Comment and both had text or at least a null.

var query = GetObject("winmgmts:").ExecQuery("SELECT Name, Status, DriverName, Comment  FROM Win32_Printer", "WQL", 0);
var e = new Enumerator(query);
for ( ; !e.atEnd(); e.moveNext ()) { 
    var p = e.item();
    WScript.Echo(p.Name + " (" + p.Status + ") " + p.DriverName + " " + p.Comment);
}
Twinscrew answered 10/6, 2009 at 0:10 Comment(2)
Thanks for the answer, but my problem is not in the query :) Regardless of the SELECT statement, properties of p object isn't discoverable (with "for") and this is ridiculous :(Heatstroke
"Yeah, I tried SELECT * from FROM Win32_Printer" and then doing for (i in p) and printing i and p.i and got nothing. But the link I posted does have all the attributes you could want, so maybe just put those in an array to get them out. All the ones I tested were there. msdn.microsoft.com/en-us/library/aa394363(VS.85).aspxTwinscrew

© 2022 - 2024 — McMap. All rights reserved.