//wmi 客户端 import com; import time.cim; namespace com; class wmi{ ctor(path,computer){ return ..com.TryGetObject("winmgmts:{impersonationLevel=Impersonate}!\\" + (computer:".") + (path || `\root\cimv2`)) }; } namespace wmi{ sink = function(event){ var sinkObj = ..com.CreateObject( "WbemScripting.SWbemSink"); ..com.Connect(sinkObj,event); return sinkObj; } query = function(wql,path,...){ if(!wql) error("缺少 WQL 参数",2); if(type(path)=="table"){ wql = formatWqlParameters(wql,path); path = ...; } elseif(...){ wql = formatWqlParameters(wql,...); } elseif( ..string.match(wql,"^[\a\d]+$") ){ wql = _alias[..string.lower(wql)] || ("Win32_" + wql); } var srv = ..com.wmi(path); if(srv){ var ret; if(..string.find(wql,"\s")) ret = srv.ExecQuery(wql,,48/*WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY*/); else ret = srv.InstancesOf(wql); ..com.Release(srv); return ret; } } queryAsync = function(sink,wql,path,...){ if(!wql) error("缺少 WQL 参数",2); if(type(path)=="table"){ wql = formatWqlParameters(wql,path); path = ...; } elseif(...){ wql = formatWqlParameters(wql,...); } elseif( ..string.match(wql,"^[\a\d]+$") ){ wql = _alias[..string.lower(wql)] || ("Win32_" + wql); } if(!..com.IsObject(sink)){ sink = ..com.wmi.sink(sink); } var srv = ..com.wmi(path); if(srv){ var ret; if(..string.find(wql,"\s")) ret = srv.ExecQueryAsync(sink,wql); else ret = srv.InstancesOf(wql); ..com.Release(srv); return ret; } } queryNotificationAsync = function(sink,wql,path,...){ if(!wql) error("缺少 WQL 参数",2); if(type(path)=="table"){ wql = formatWqlParameters(wql,path); path = ...; } elseif(...){ wql = formatWqlParameters(wql,...); } elseif( ..string.match(wql,"^[\a\d]+$") ){ wql = _alias[..string.lower(wql)] || ("Win32_" + wql); } if(!..com.IsObject(sink)){ sink = ..com.wmi.sink(sink); } var srv = ..com.wmi(path); if(srv){ var ret; if(..string.find(wql,"\s")) ret = srv.ExecNotificationQueryAsync(sink,wql); else ret = srv.InstancesOf(wql); ..com.Release(srv); return ret; } } queryNotification = function(wql,path,...){ if(!wql) error("缺少 WQL 参数",2); if(type(path)=="table"){ wql = formatWqlParameters(wql,path); path = ...; } elseif(...){ wql = formatWqlParameters(wql,...); } elseif( ..string.match(wql,"^[\a\d]+$") ){ wql = _alias[..string.lower(wql)] || ("Win32_" + wql); } var srv = ..com.wmi(path); if(srv){ var ret; if(..string.find(wql,"\s")) ret = srv.ExecNotificationQuery(wql,,48/*WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY*/); else ret = srv.InstancesOf(wql); ..com.Release(srv); return ret; } } get = function(wql,property,path,...){ if(!wql) error("缺少 WQL 参数",2); var items; if(type.isString(property) && ..string.match(property,"^\w+$") ){ if( ..string.match(wql,"^\w+$") ){ if(!..string.indexAny(wql,'_'#)) wql = _alias[..string.lower(wql)] || ("Win32_" + wql); wql = "SELECT "+property+" FROM "+wql; } items = query(wql,path,...); } else{ if(property!==null){ items = query(wql,property/*表参数*/,path,...); property = null; } else{ items = query(wql,path/*也可能是表参数*/,...); } } if( items ) { var item = ..com.first(items); ..com.Release(items); if(item && property) { var ret = item[property]; if(type.isString(ret) && (#ret == 25) ){ var d = ..time.cim(ret); if(d) return d; } ..com.Release(item); return ret; } return item; } } getProperties = function(wql,path,...){ if(!wql) return; var wqlIsObj = ..com.IsObject(wql); var item = wqlIsObj ? wql : get(wql,,path,...); if(item){ var ret = {}; var p = item.properties_; for index,obj in ..com.each(p) { ret[obj.Name] = obj.Value; ..com.Release(obj); } ..com.Release(p); if(!wqlIsObj) ..com.Release(item); return ret; } } each = function(wql,path,...){ var items = query(wql,path,...); if( items ) { var next,free = ..com.each(items); ..com.Release(items); return next,free; } return function(){} } eachNotification = function(wql,path,...){ var eventSource = queryNotification(wql,path,...); if( eventSource ) { return function(){ var e = eventSource.NextEvent() if(e){ return e,e.TargetInstance; } },function(){ ..com.Release(eventSource); } } return function(){} } eachProperties = function(wql,path,...){ if(!wql) return; var items = query(wql,path,...); if( items ) { var next,free = ..com.each(items); ..com.Release(items); return function(){ var i,item = next(); if(item) { var r = getProperties(item); ..com.Release(item); return r,i; } },free; } return function(){} } getTable = function(wql,path,...){ var tab = []; for item in eachProperties(wql,path,...){ ..table.push(tab,item) } return tab; } escape = function(v){ var t = type(v); if( t = "string"){ return '"' + ..string.replace(v,`['"\\]`,"\\\1") + '"'; } elseif( t = "boolean" ){ return v ? "1" : "0"; } elseif( t = "number" ){ return tostring(v); } elseif( t = "table" ) { if(..time.istime(v)){ return ..time.cim(v).format("!'%Y%m%d%H%M%S.000000+000'"); } } return ..string.replace(tostring(v),"\p",""); }; formatWqlParameters = function(wql,...) { if( type( ... ) == "table" ){ var param = ...; if(#param){ var i = 0; wql = (..string.replace(wql,"\?", function(name) { i++; return escape(param[i]); } )); } return (..string.replace(wql,"\@(<:+>|<\w+>[^\s\p]*)", lambda(name) escape(param[name]) )); } return ..string.format(wql,...); } _alias = { alias="Msft_CliAlias"; bootconfig="Win32_BootConfiguration"; cdrom="Win32_CDROMDrive"; cpu="WIN32_PROCESSOR"; csproduct="Win32_ComputerSystemProduct"; datafile="CIM_DataFile"; dcomapp="WIN32_DCOMApplication"; desktop="WIN32_DESKTOP"; desktopmonitor="WIN32_DESKTOPMONITOR"; fsdir="Win32_Directory"; idecontroller="Win32_IDEController"; irq="Win32_IRQResource"; job="Win32_ScheduledJob"; loadorder="Win32_LoadOrderGroup"; logon="Win32_LogonSession"; memcache="WIN32_CACHEMEMORY"; memorychip="Win32_PhysicalMemory"; memphysical="Win32_PhysicalMemoryArray"; netclient="WIN32_NetworkClient"; netlogin="Win32_NetworkLoginProfile"; netprotocol="Win32_NetworkProtocol"; netuse="Win32_NetworkConnection"; nic="Win32_NetworkAdapter"; nicconfig="Win32_NetworkAdapterConfiguration"; ntdomain="Win32_NTDomain"; ntevent="Win32_NTLogEvent"; nteventlog="Win32_NTEventlogFile"; os="Win32_OperatingSystem"; pagefile="Win32_PageFileUsage"; pagefileset="Win32_PageFileSetting"; partition="Win32_DiskPartition"; port="Win32_PortResource"; printerconfig="Win32_PrinterConfiguration"; qfe="Win32_QuickFixEngineering"; rdaccount="Win32_TSAccount"; rdnic="Win32_TSNetworkAdapterSetting"; rdpermissions="Win32_TSPermissionsSetting"; rdtoggle="Win32_TerminalServiceSetting"; recoveros="Win32_OSRecoveryConfiguration"; scsicontroller="Win32_SCSIController"; server="Win32_PerfRawData_PerfNet_Server"; sounddev="WIN32_SoundDevice"; startup="Win32_StartupCommand"; sysaccount="Win32_SystemAccount"; sysdriver="Win32_SystemDriver"; temperature="Win32_TemperatureProbe"; ups="Win32_UninterruptiblePowerSupply"; voltage="Win32_VoltageProbe"; wmiset="Win32_WMISetting" } } //@guide [💻 WMI 查询入门](doc://example/COM/WMI/query.aardio) [📈 WMI 事件回调](doc://example/COM/WMI/SWbemSink.aardio) /**intellisense() com.wmi = WMI / Windows Management Instrumentation 客户端。\n用法也可可参考 com.monitor 库源码,以及『 范例 » COM 组件 » WMI 』。\n参考文档 https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-reference com.wmi( = 创建 WMI 客户端对象,失败返回 null com.wmi(.(path,computer) = 创建并返回 WMI 客户端对象,失败返回 null,\n所有参数可省略,\n@path 默认为 `\root\cimv2`\n@computer 默认为"." com.wmi() = !stdComObject. com.wmi._alias = 这是一个表对象指定了 WMI 类的别名。 com.wmi 库函数的 WQL 参数在指定单个类名时可使用别名或省略 "Win32_"前缀。\n指定类名时忽略大小写,com.wmi._alias 中的键名则必须小写。\ncom.wmi._alias 的别名可用于 wmic,\n但这个表不包含仅省略"Win32_"前缀的别名(aardio 会自动加这个前缀)。 com.wmi.sink(event) = @.sink(\n OnCompleted = function(hResult,wbemErrorObject,wbemAsyncContext){\n \n };\n OnObjectPut = function(wbemObjectPath,wbemAsyncContext){\n \n };\n OnObjectReady = function(wbemObject,wbemAsyncContext){\n \n };\n OnProgress = function(upperBound,current,message,wbemAsyncContext){\n \n };\n) com.wmi.query( = 调用 ExecQuery 执行 WQL 查询,返回查询结果。 com.wmi.query(.(wql,parameters,path) = 参数 @wql 指定 WQL 查询语句。\n可选参数 @parameters 可使用一个表对象指定 WQL 参数值。\n- 表中的命名值指定 WQL 语句中 `@`号 开头的命名参数值。\n- 表中的数组值指定 WQL 语句中以 `?` 号为占位符的数组参数的值。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。 com.wmi.get( = 可输入 WQL 查询语句或类名,\n如果成功则返回查询结果中的第一个元素。 com.wmi.get(.(wql) = 参数 @wql 可输入 WQL 查询语句或类名。\n仅指定类名时可省略 "Win32_"前缀。\n成功则返回查询结果的首个元素( COM 对象 )。\n要注意此函数返回的是单个元素,不一定是能用 com.each 遍历的集合对象。 com.wmi.get(.(wql,property) = 参数 @wql 可输入 WQL 查询语句。\n可选用参数 @property 指定要取的属性名(只能包含字母、数字、下划线)。\n成功则返回查询结果的首个元素指定属性的值,失败返回 null。\n如果返回值为 CIM_DATETIME 格式的时间字符串,则转换为 time.cim 时间对象。\n\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。\n可选用参数 @3 及后续参数指定格式化参数。\n如果指定了格式化参数则调用 string.format 格式化参数 @wql 。 com.wmi.get(.(className,property,path) = 参数 @className 指定 WMI 类名,可省略 "Win32_"前缀 。\n参数 @property 指定要取的属性名(只能包含字母、数字、下划线)。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。\n\n成功则返回查询结果的首个元素指定属性的值,失败返回 null。\n如果返回值为 CIM_DATETIME 格式的时间字符串,则转换为 time.cim 时间对象。\n\n例如 aardio 代码 `com.wmi.get("diskdrive","serialnumber")`\n的返回的字符串值与执行 `wmic diskdrive get serialnumber` 命令输出的字符串相同。 com.wmi.get(.(wql,parameters,path) = \n参数 @wql 指定 WQL 查询语句\n可选参数 @parameters 可使用一个表对象指定 WQL 参数值。\n- 表中的命名值指定 WQL 语句中 `@`号 开头的命名参数值。\n- 表中的数组值指定 WQL 语句中以 `?` 号为占位符的数组参数的值。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。\n成功则返回首个查询结果(返回 COM 对象),失败返回 null。\n要注意返回结果中的第一个元素如果不是集合则不能也不需要用 com.each 遍历。\n如果要返回纯 aardio 值可改用 com.wmi.getProperties 。 com.wmi.getProperties( = 执行 WQL 查询并获取查询结果内的首个元素。\n成功返回包含查询结果内首个元素有效属性名值对的纯表对象(非 COM 对象)。 \n失败返回 null 值。 com.wmi.getProperties(.(wql,parameters,path) = 参数 @wql 指定 WQL 查询语句。\n可选参数 @parameters 可使用一个表对象指定 WQL 参数值。\n- 表中的命名值指定 WQL 语句中 `@`号 开头的命名参数值。\n- 表中的数组值指定 WQL 语句中以 `?` 号为占位符的数组参数的值。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。 com.wmi.getProperties(.(wmiObject) = 将参数 @wmiObject 指定 WMI 对象转换为普通的表对象。\n返回包含该对象所有属性名值对的表对象。\n失败返回 null com.wmi.getTable( = 执行 WQL 查询并返回一个包含了所有查询结果的纯数组。\n数组元素为包含 WMI 对象所有属性名值对的属性表(纯值表,非 COM 对象)。\n失败返回 null 值。 com.wmi.getTable(.(wql,parameters,path) = 参数 @wql 指定 WQL 查询语句。\n可选参数 @parameters 可使用一个表对象指定 WQL 参数值。\n- 表中的命名值指定 WQL 语句中 `@`号 开头的命名参数值。\n- 表中的数组值指定 WQL 语句中以 `?` 号为占位符的数组参数的值。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。 com.wmi.queryAsync( = 执行异步 WQL 查询。 com.wmi.queryAsync(.(objSink,wql,parameters,path) = 参数 @objSink 可指定包含了回调事件的表对象或 com.wmi.sink 对象。\n参数 @wql 指定 WQL 查询语句。\n可选参数 @parameters 可使用一个表对象指定 WQL 参数值。\n- 表中的命名值指定 WQL 语句中 `@`号 开头的命名参数值。\n- 表中的数组值指定 WQL 语句中以 `?` 号为占位符的数组参数的值。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。 com.wmi.queryNotificationAsync( = 执行异步 WQL 查询以接收事件。 com.wmi.queryNotificationAsync(.(objSink,wql) = 参数 @objSink 可指定包含了回调事件的表对象或 com.wmi.sink 对象。\n参数 @objSink 可指定 com.wmi.sink 对象或者指定了普通表对象。\n参数 @wql 可输入 WQL 查询语句或 WMI 类名。\n仅指定类名时可省略 "Win32_" 前缀或使用 com.wmi._alias 注册的别名。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。 com.wmi.queryNotificationAsync(.(objSink,wql,parameters,path) = 参数 @objSink 可指定包含了回调事件的表对象或 com.wmi.sink 对象。\n参数 @wql 指定 WQL 查询语句。\n可选参数 @parameters 可使用一个表对象指定 WQL 参数值。\n- 表中的命名值指定 WQL 语句中 `@`号 开头的命名参数值。\n- 表中的数组值指定 WQL 语句中以 `?` 号为占位符的数组参数的值。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`。 com.wmi.each(wqlOrObject,parameters,path) = @for index,item in com.wmi.each("__/*遍历参数 @wqlOrObject 指定的 WMI 对象。\n参数 @wqlOrObject 也可以指定 WQL 查询语句或 WMI 类名。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`\n\n可选用参数 @parameters 指定包含 WQL 参数值的表对象,\n包含 WQL 语句中 `@` 号开头的命名参数值或以 `?` 号为占位符的匿名参数值(数组成员) */") { } com.wmi.eachNotification(wqlOrObject,parameters,path) = @for event,targetInstance in com.wmi.eachNotification("__/*遍历参数 @wqlOrObject 指定的查询事件通知,同步阻塞执行。\n参数 @wqlOrObject 也可以输入 WQL 查询语句或 WMI 类名。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`\n\n可选用参数 @parameters 指定包含 WQL 参数值的表对象,\n包含 WQL 语句中 `@` 号开头的命名参数值或以 `?` 号为占位符的匿名参数值(数组成员) */") { } com.wmi.eachProperties(wqlOrObject,parameters,path) = @for item,index in com.wmi.eachProperties("__/*遍历参数 @wqlOrObject 指定的 WMI 对象的属性表。\n参数 @wqlOrObject 也可以输入 WQL 查询语句或 WMI 类名。\n可选用参数 @path 指定 WMI 路径,默认为 `\root\cimv2`\n\n可选用参数 @parameters 指定包含 WQL 参数值的表对象,\n包含 WQL 语句中 `@` 号开头的命名参数值或以 `?` 号为占位符的匿名参数值(数组成员) */") { } com.wmi.formatWqlParameters( = 格式化参数 @1 指定的 WQL 语句,\ncom.wmi.query 等函数调用此函数格式化 WQL 语句 com.wmi.formatWqlParameters(.(wql,->->->) = 格式化参数 @1 指定的 WQL 语句,\n参数@2及后续参数指定格式化参数,\n支持 @号 开头的命名参数或以 ? 号为占位符的匿名参数,\n如果参数不是一个表,则调用 string.format 格式化 com.wmi.each() = !SWbemObject. com.wmi.get() = !SWbemObject. end intellisense**/ /**intellisense(!stdComObject) ExecQuery("SELECT * FROM Win32_BaseBoard__") = 使用 WQL 进行查询,返回 COM 对象,\n参数@2必须省略,可选用参数@3指定选项,\n半同步优化请将参数@3指定以下值 _wbemFlagReturnImmediately | _wbemFlagForwardOnly\n更多参数说明请参考 https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemservices-execquery ExecQueryAsync(.(sinkObj,wqlQuery) = 异步查询对象,\n参数@1必须传入 com.wmi.sink 创建的对象,\n参数@2指定 WQL 查询语句。\n更多参数说明请参考 https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemservices-execqueryasync ExecNotificationQueryAsync(.(sinkObj,wqlQuery) = 执行异步查询以接收事件,\n参数@1必须传入 com.wmi.sink 创建的对象,\n参数@2指定 WQL 查询语句\n更多参数说明请参考 https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemservices-execnotificationquery ExecNotificationQuery(.(wqlQuery) = 执行查询并接收事件 InstancesOf(.(strClass,iFlags) = 根据指定的类名,返回可使用 com.each 遍历的对象 end intellisense**/ /**intellisense() _wbemFlagReturnImmediately=@16/*_wbemFlagReturnImmediately*/ _wbemFlagForwardOnly=@32/*_wbemFlagForwardOnly*/ end intellisense**/ /**intellisense(!SWbemObject) Put_() = 创建或更新 WMI 对象,\n修改属性后要调用这个函数才会生效,\n进程可能需要管理权限 PutAsync_ = 异步创建或更新 WMI 对象 Delete_ = 删除对象 end intellisense**/