Перечислитель JScript и список свойств


Рассмотрим следующий фрагмент WSH:

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 + ")");
}

Он печатает в каждой строке имя принтера и слово "undefined" в скобках (потому что свойство Status не существует в объекте p). Вопрос в следующем: как я могу перечислить все доступные свойства из p? Обычная техника с for (var i in p) {...} не работает-похоже, что свойства в объекте p не поддаются перечислению.

Заранее благодарю.

3 6
wsh

3 ответа:

Оператор

JScript for...in несовместим с объектами WMI, поскольку они более сложны, чем собственные объекты JScript. Объекты WMI предоставляют свою коллекцию свойств через специальный Properties_ таким образом, чтобы перечислить все доступные свойства объекта, необходимо перечислить эту коллекцию, как вы перечисляете результаты запроса для доступа к отдельным объектам WMI. Каждое свойство объекта представлено a SWbemProperty объект, который имеет Name, Value и другие свойства предоставление информации о соответствующем свойстве объекта.

Этот пример должен помочь вам понять идею:

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);
    }
}
Обратите внимание, что этот скрипт также будет отображать значение свойства DeviceID, поскольку это ключевое свойство класса Win32_Printer, поэтому оно также извлекается для уникальной идентификации экземпляров класса.

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

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

Итерация по коллекциям тогда становится несколько менее неуклюжей:

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);
    });
});

Я думаю, что проблема в вашем запросе, вы спрашиваете только имя. Попробуйте спросить и имя, и статус:

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 + ")" );
}

Я получил еще несколько свойств от http://msdn.microsoft.com/en-us/library/aa394363 (VS.85).aspx и несколько работ. Я запросил имя драйвера и комментарий, и оба имели текст или, по крайней мере, 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);
}