Jump to content
Sign in to follow this  
Irios

How to enumerate all properties in an object variable (wmi) when I don't know their names? [SOLVED!]

Recommended Posts

First post here, please be gentle ;)

 

I've spent hours and hours trying to figure out this puzzle. It's impossible to google for because I don't know the precise terminology to use. All msdn links I find are either dead or has been removed like 10 years ago.

 

Here is a tiny code example:

$objWMIService = ObjGet("winmgmts:")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface Where Name like '%intel%'")
For $objItem In $colItems
    ConsoleWrite($objItem.PacketsPersec & @CRLF)
Next

In that example I'm using the asterix * and it retrieves all properties in the "Win32_PerfRawData_Tcpip_NetworkInterface" class.  But I'm only utilizing "PacketsPersec" in the example.

How could I enumerate all the properties without defining their names beforehand?

(FYI, I do know their names, but the script doesn't know the names)

In other words; how can I use "SELECT *" on any class and output all properties, one by one? Without having to manually specify each property with $objItem.<propertyname> ?


As comparison, using wmic in a cmd shell ...

    wmic path Win32_PerfRawData_Tcpip_NetworkInterface  Where "Name like '%intel%'" get /value

...and it lists all properties in "Names=Value" manner.

This is sort of the same function I'm looking for. How could I do the same in Autoit?

 

 

EDIT: I cannot run a powershell or cmd  to "solve" the problem.  I need to find a way to do this "internally" in Autoit. I.e. by calling the WMI service directly with ObjGet(winmgmts:) or connect to the WMI system with CreateObject("WbemScripting.SWbemLocator"). Performance is a major factor.

Edited by Irios
Solved! :D

Share this post


Link to post
Share on other sites
Local $strComputer = "."
Local $strNameSpace = "root\cimv2"
Local $strClass = "Win32_PerfRawData_Tcpip_NetworkInterface"

Local $objClass = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\" & $strNameSpace & ":" & $strClass)
For $objClassProperty In $objClass.Properties_
    ConsoleWrite($objClassProperty.Name & @CRLF)
Next

 


Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites

Hi there, Terenz.

I must admit I already had a look into ".Properties_" earlier on, but I don't understand its inner workings, tbh. Or rather, I don't know how to get BOTH the property names AND values... in one go.

In your script example... if you output "$objClass.Value" as well, it is just empty. (I'm guessing it's not really the Value for the property at all)

; ../..
ConsoleWrite($objClassProperty.Value & @CRLF)
; ../..

 

Is it a different object "type" altogether? This is my problem, I'm having a hard time getting a grasp on these objects (where do I start to read about this?), and how are they structured internally? (Do you have any simple examples to illustrate this? Or an info page link?)

I could use your script example combined with my own script to get both property names and their respective values, but it's not very efficient and you're then doing two wmi calls. There must be a way to do this in a single run.

Share this post


Link to post
Share on other sites

Hi @Irios perhaps you can try WMI Explorer. Its a tool for displaying WMI Namespaces, Classes and Properties. WMI Explorer
A Way to get both the property and value written to the console is in the example below.

Local $objWMIService = ObjGet("winmgmts:\\" & "." & "\root\CIMV2")
Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PerfRawData_Tcpip_TCP")

If IsObj($colItems) then
   For $objItem In $colItems
      ConsoleWrite ("Caption: " & $objItem.Caption & @CRLF )
      ConsoleWrite ("ConnectionFailures: " & $objItem.ConnectionFailures & @CRLF )
      ConsoleWrite ("ConnectionsActive: " & $objItem.ConnectionsActive & @CRLF )
      ConsoleWrite ("ConnectionsEstablished: " & $objItem.ConnectionsEstablished & @CRLF )
      ConsoleWrite ("ConnectionsPassive: " & $objItem.ConnectionsPassive & @CRLF )
      ConsoleWrite ("ConnectionsReset: " & $objItem.ConnectionsReset & @CRLF )
      ConsoleWrite ("Description: " & $objItem.Description & @CRLF )
      ConsoleWrite ("Frequency_Object: " & $objItem.Frequency_Object & @CRLF )
      ConsoleWrite ("Frequency_PerfTime: " & $objItem.Frequency_PerfTime & @CRLF )
      ConsoleWrite ("Frequency_Sys100NS: " & $objItem.Frequency_Sys100NS & @CRLF )
      ConsoleWrite ("Name: " & $objItem.Name & @CRLF )
      ConsoleWrite ("SegmentsPersec: " & $objItem.SegmentsPersec & @CRLF )
      ConsoleWrite ("SegmentsReceivedPersec: " & $objItem.SegmentsReceivedPersec & @CRLF )
      ConsoleWrite ("SegmentsRetransmittedPersec: " & $objItem.SegmentsRetransmittedPersec & @CRLF )
      ConsoleWrite ("SegmentsSentPersec: " & $objItem.SegmentsSentPersec & @CRLF )
      ConsoleWrite ("Timestamp_Object: " & $objItem.Timestamp_Object & @CRLF )
      ConsoleWrite ("Timestamp_PerfTime: " & $objItem.Timestamp_PerfTime & @CRLF )
      ConsoleWrite ("Timestamp_Sys100NS: " & $objItem.Timestamp_Sys100NS & @CRLF )
   Next
Else
    Msgbox (48, "WMI Error", "WMI Error")
Endif

 

Share this post


Link to post
Share on other sites

Hi pluto41,

Like I wrote in my initial post, I need a way to do it without having to define all the property names beforehand in the code. (Your example will only output properties you specifically define in the code). I want to gather all properties (SELECT *), no matter the name, and then output the Name and its respective Value.

 

EDIT: You refer to WMI Explorer 2... if you use the PowerShell output there... See how it's done with PS? The script actually parses the WMI data and displays it as "Property : Value"... without having to define each Property first. That's  what I'm looking for in AutoIt.

 

WMI Explorer 2 Powershell example:

$computer = $env:COMPUTERNAME
$namespace = "ROOT\CIMV2"
$classname = "Win32_PerfRawData_Tcpip_NetworkInterface"

 

Get-WmiObject -Class $classname -ComputerName $computer -Namespace $namespace |

    Select-Object * -ExcludeProperty PSComputerName, Scope, Path, Options, ClassPath, Properties, SystemProperties, Qualifiers, Site, Container |
    Format-List -Property [a-z]*

 

 

 

 

WMI Explorer 2 Powershell example output:

BytesReceivedPersec             : 105906295
BytesSentPersec                 : 1472390918
BytesTotalPersec                : 1578297213
Caption                         :
CurrentBandwidth                : 1000000000
Description                     :
Frequency_Object                : 0
Frequency_PerfTime              : 3521210
Frequency_Sys100NS              : 10000000
Name                            : Intel[R] 82579V Gigabit Network Connection
OffloadedConnections            : 0
OutputQueueLength               : 0
PacketsOutboundDiscarded        : 0
PacketsOutboundErrors           : 0
PacketsPersec                   : 1440415
PacketsReceivedDiscarded        : 0
PacketsReceivedErrors           : 0
PacketsReceivedNonUnicastPersec : 23105
PacketsReceivedPersec           : 313482
PacketsReceivedUnicastPersec    : 290377
PacketsReceivedUnknown          : 0
PacketsSentNonUnicastPersec     : 3858
PacketsSentPersec               : 1126933
PacketsSentUnicastPersec        : 1123075
Timestamp_Object                : 0
Timestamp_PerfTime              : 13100603957
Timestamp_Sys100NS              : 131179061249680000

Edited by Irios

Share this post


Link to post
Share on other sites

@Irios if you're looking for both the property name and the value in a single pass I would do something like this:

Local $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Local $oItems = $oWMI.ExecQuery("Select * FROM Win32_PerfRawData_Tcpip_NetworkInterface")
    For $sItem In $oItems
        For $sProperty In $sItem.Properties_
            ConsoleWrite($sProperty.Name & ": " & $sProperty.Value & @CRLF)

        Next
    Next

 Just be aware that some properties may return an array rather than a string. So you might have to code a For loop to gather all the values.


"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Share this post


Link to post
Share on other sites

Oke @Irios I understand what you mean. Very interesting problem. I spend a hour or so to play a bit with the concept but i can't get it to work :( Anyway this is my try.

Local $strComputer = "."
Local $strNameSpace = "root\cimv2"
Local $strClass = "Win32_PerfRawData_Tcpip_NetworkInterface"
Local $objClass = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\" & $strNameSpace & ":" & $strClass)

Local $objWMIService = ObjGet("winmgmts:\\" & "." & "\root\CIMV2")

Local $colItems
For $objProperty In $objClass.Properties_
    ConsoleWrite ( "=========> " & $objProperty.Name & " " )
    $colItems = $objWMIService.ExecQuery("SELECT " & $objProperty.Name & " FROM Win32_PerfRawData_Tcpip_TCP")
    For $objItem in $colItems
        ; Oke does not work but we are in the loop so something is going on here.
        Local $sValue = Execute ($objItem.Name)     ; attempt to retrieve the contents of $objItem.Name rather then the object.property itself.
        ConsoleWrite ( "Value : " & $sValue & @CRLF )
    Next
Next

 

Share this post


Link to post
Share on other sites
28 minutes ago, JLogan3o13 said:

@Irios if you're looking for both the property name and the value in a single pass I would do something like this:

../..

Super thanks, @JLogan3o13

That was exactly what I was looking for!

 

 

 

Share this post


Link to post
Share on other sites

@JLogan3o13 Yup good job! This was exactly where i was after but now i see you use ExecQuery and i used the code posted earlier in the topic.

Local $strComputer = "."
Local $strNameSpace = "root\cimv2"
Local $strClass = "Win32_PerfRawData_Tcpip_NetworkInterface"

Local $objClass = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\" & $strNameSpace & ":" & $strClass)
For $objClassProperty In $objClass.Properties_
    ConsoleWrite($objClassProperty.Name & @CRLF)
    ConsoleWrite($objClassProperty.Value & @CRLF)   ; does not work!!!
Next

In this case there isn't a .Value so i tried to program around it. Which wasn't a succes :P Thanks for sharing your'e code. Excellent! (y)

Share this post


Link to post
Share on other sites

So, now that I have a solution, I still don't understand how to know where to use ".Properties_" and what I might expect find inside it. I do know in regard of WMI Classes and their Properties, of course. That's what this example was about.

Is there some kind of reference where i can learn about this? You have no idea the amount of time I've spent on this little problem now, and I'm not really getting anywhere. Just copying in a solution given by someone else doesn't really provide the basis for expanding and exploring these objects further.

I've had a look at OleView.Exe, but that doesn't help me at all. Just as stuck. I can't even find any wmi classes or namespaces in there :/

 

Share this post


Link to post
Share on other sites

@pluto41

I've more or less already tried those approaches you suggested, in one way or another. And, yeah you can sort of make it do the job, but not in a very efficient way. I really wanted a way do it "in one go". After all, PS and WMIC could do it. I knew it was possible, I just couldn't figure it out myself.

Share this post


Link to post
Share on other sites

@Irios the only way you're going to learn WMI in depth is to do a lot of reading: https://msdn.microsoft.com/en-us/library/aa394582(v=vs.85).aspx


"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Share this post


Link to post
Share on other sites

Yeah, the basics of WMI (retrieving data) isn't something I'm struggling with, to be honest. I've been using WMIC and WQL for quite a while, so I know those things pretty good now.

But using objects to retrieve data from WMI is brand new to me. COM, WBEM, etc. I really don't know where to start. It's quite overwhelming, and I figured if I'd just get a few starters by googling some practical examples, I might figure it out by myself. But no, haha. Like you say, I've obviously got a lot of reading ahead of me :D

Edited by Irios
letters and words

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By DirtyJohny
      Hi everyone.Need rewrite this function how in еxample.
      Original:
      #RequireAdmin #NoTrayIcon Opt("MustDeclareVars",1) Func _a() Local $sls=ObjGet("winmgmts:{impersonationLevel=impersonate," _ &"authenticationLevel=Pkt}!\\"& _ @ComputerName&'\root\wmi'),$lss=$sls.ExecQuery _ ('SELECT * FROM WmiMonitorID'), _ $lll,$sll,$sss="",$lsl,$lls,$i,$z For $z In $lss $lsl=$z.UserFriendlyName For $i=0 To Ubound($lsl)-1 if ($lsl[$i]) Then $lll&=Chr($lsl[$i]) Next $lls=$z.SerialNumberID For $i=0 To Ubound($lls)-1 if ($lls[$i]) Then $sll&=Chr($lls[$i]) Next $sss&="Model"&@TAB&@TAB&": "&$lll&@CR&"Serial Number"&@TAB&": "&$sll&@CR&@CR $lll="" $sll="" Next MsgBox(262144,'Monitors '&$lss.Count,$sss&" "&@CR) $lss=Null $sls=Null EndFunc _a() Example:
      Func _InfoPC() Local $ObjService = ObjGet('winmgmts:{impersonationLevel = impersonate}!\\' & @ComputerName & '\root\cimv2') Local $ObjMB = $ObjService.ExecQuery('SELECT * FROM Win32_BaseBoard', 'WQL', 0x30) If IsObj($ObjService) Then For $objItemMB In $ObjMB $sInfo &= @TAB & 'Motherboard: ...... ' & $objItemMB.Product & @CRLF I'm beginner in this sphere and need  you all speak easy and simply because i'm Russian.Thanks)
    • By jguinch
      Hello.
      I did create these few functions several months ago. I post here, if it can interest someone.
      These functions based on WMI queries allow you to manage printers : add / delete printer, driver, port, or obtain configuration, set default printer ... I let you discover it with the code.

       
      Here is the list of the available functions :
      _Printmgr_AddLocalPort
      _Printmgr_AddLPRPort
      _PrintMgr_AddPrinter
      _PrintMgr_AddPrinterDriver
      _PrintMgr_AddTCPIPPrinterPort
      _PrintMgr_AddWindowsPrinterConnection
      _PrintMgr_CancelAllJobs
      _Printmgr_EnumPorts
      _PrintMgr_EnumPrinter
      _PrintMgr_EnumPrinterConfiguration
      _PrintMgr_EnumPrinterDriver
      _PrintMgr_EnumPrinterProperties
      _PrintMgr_EnumTCPIPPrinterPort
      _Printmgr_Pause
      _Printmgr_PortExists
      _Printmgr_PrinterExists
      _Printmgr_PrinterSetComment
      _Printmgr_PrinterSetDriver
      _Printmgr_PrinterSetPort
      _Printmgr_PrinterShare
      _Printmgr_PrintTestPage
      _PrintMgr_RemoveLocalPort
      _PrintMgr_RemoveLPRPort
      _PrintMgr_RemovePrinter
      _PrintMgr_RemovePrinterDriver
      _PrintMgr_RemoveTCPIPPrinterPort
      _PrintMgr_RenamePrinter
      _Printmgr_Resume
      _PrintMgr_SetDefaultPrinter
       
      And some examples :
      #include <Array.au3> #include "PrintMgr.au3" _Example() Func _Example() ; Remove a printer called "My old Lexmark printer" : _PrintMgr_RemovePrinter("My old Lexmark printer") ; Remove the driver called "Lexmark T640" : _PrintMgr_RemovePrinterDriver("Lexmark T640") ; Remove the TCP/IP printer port called "TCP/IP" _PrintMgr_RemoveTCPIPPrinterPort("MyOLDPrinterPort") ; Add a driver, called "Samsung ML-451x 501x Series", and driver inf file is ".\Samsung5010\sse2m.inf" _PrintMgr_AddPrinterDriver("Samsung ML-451x 501x Series", "Windows NT x86", @ScriptDir & "\Samsung5010", @ScriptDir & "\Samsung5010\sse2m.inf") ; Add a TCP/IP printer port, called "MyTCPIPPrinterPort", with IPAddress = 192.168.1.10 and Port = 9100 _PrintMgr_AddTCPIPPrinterPort("MyTCPIPPrinterPort", "192.168.1.10", 9100) ; Add a printer, give it the name "My Printer", use the driver called "Samsung ML-451x 501x Series" and the port called "MyTCPIPPrinterPort" _PrintMgr_AddPrinter("My Printer", "Samsung ML-451x 501x Series", "MyTCPIPPrinterPort") ; Set the printer called "My Printer" as default printer _PrintMgr_SetDefaultPrinter("My Printer") ; Connect to the shared printer "\\192.168.1.1\HPDeskjetColor") _PrintMgr_AddWindowsPrinterConnection("\\192.168.1.1\HPDeskjetColor") ; List all installed printers Local $aPrinterList = _PrintMgr_EnumPrinter() _ArrayDisplay($aPrinterList) ; List all printers configuration Local $aPrinterConfig = _PrintMgr_EnumPrinterConfiguration() _ArrayDisplay($aPrinterConfig) ; List all installed printer drivers Local $aDriverList = _PrintMgr_EnumPrinterDriver() _ArrayDisplay($aDriverList) ; Retrieve the printer configuration for the printer called "Lexmark T640" $aPrinterConfig = _PrintMgr_EnumPrinterConfiguration("Lexmark T640") _ArrayDisplay($aPrinterConfig) ; Add a local printer port (for a file output) _PrintMgr_AddLocalPort("c:\temp\output.pcl") ; Remove the local port _PrintMgr_RemoveLocalPort("c:\temp\output.pcl") EndFunc ;==>_Example Download link :
      PrintMgr.au3
      PrintMgr_Example.au3
    • By shital
      #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** RunAs(test", @ComputerName, "testinng",2,"wmic product where ""name= '%notepadexamples%'"" call uninstall", @SystemDir & "\wbem", @SW_MAXIMIZE)  it not working 
       
    • By Colduction
      Hi AutoIt Programmers!

      I've seen a code that gives Name of Group by writing it's group's SID, but this one response very slower than Windows Command-Line WMIC
       
      Func _GetLocalGroupName($sSID = 'S-1-5-18') $objWMIService = ObjGet ("winmgmts:\\" & @ComputerName & "\root\cimv2") $colItems = $objWMIService.ExecQuery('SELECT Name FROM Win32_Group where SID="' & $sSID & '"') For $GroupNames in $colItems MsgBox (0,"",$GroupNames.Name) ExitLoop Next EndFunc I don't want call and use any third-party programs even CMD, i just want use from Windows API, netapi32.dll or AutoIt Functions (Standalone).
      Do you have any idea to improve speed/performance of this code? I'll happy of your comments
       
       
       
      ====================== SOLOUTION by @Subz ======================
       
    • By jresine
      Hello, is it possible to know via a script or command, to have the percentage of disk usage of a process? thank you in advance.
      ps: see image

×
×
  • Create New...