【问题标题】:JScript Enumerator and list of propertiesJScript 枚举器和属性列表
【发布时间】:2009-06-09 23:29:55
【问题描述】:

考虑以下 WSH sn-p:

var query = GetObject("winmgmts:").ExecQuery("SELECT Name FROM Win32_Printer", "WQL", 0); var e = new 枚举器(查询); 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 对象中的属性似乎不可枚举。

提前致谢。

【问题讨论】:

    标签: jscript wsh


    【解决方案1】:

    JScript 的for...in 语句与WMI 对象不兼容,因为它们比本机JScript 对象更复杂。 WMI 对象通过特殊的Properties_ 属性公开其属性集合,因此要列出对象的所有可用属性,您需要像枚举查询结果一样枚举该集合以访问各个WMI 对象。每个对象属性都由一个 SWbemProperty 对象表示,该对象具有 NameValue 和其他提供有关相应对象属性信息的属性。

    这个例子应该可以帮助你理解这个想法:

    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 类的关键属性,因此也检索它以唯一标识类实例。

    【讨论】:

    • @HenryFlower 尽管我很喜欢那些西里尔字母,但最好在这里用英文写 :) 顺便说一句,我不认为“Henry Flower”来自俄罗斯!
    【解决方案2】:

    如果您想避免每次需要遍历需要枚举的集合对象时都使用显式枚举器,您可以定义一个像这样的小辅助函数:

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

    【讨论】:

    • 由于您不能直接从回调函数中将break 退出循环,因此在循环中包含返回值条件检查可能是个好主意,例如if(func(e.item()) === false) break;,允许您在需要突破时从回调中return false
    【解决方案3】:

    我认为问题出在您的查询中,您只询问名称。尝试同时询问姓名和状态:

    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 获得了更多属性和一些工作。我查询了 DriverName 和 Comment,两者都有文本或至少为空。

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

    【讨论】:

    • 感谢您的回答,但我的问题不在查询中 :) 无论 SELECT 语句如何,都无法发现 p 对象的属性(使用“for”),这很荒谬 :(
    • “是的,我尝试了 SELECT * from FROM Win32_Printer”,然后执行 for (i in p) 并打印 i 和 p.i,但一无所获。但是我发布的链接确实具有您可能想要的所有属性,所以也许只需将它们放在一个数组中以将它们取出。我测试的所有东西都在那里。 msdn.microsoft.com/en-us/library/aa394363(VS.85).aspx
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多