Jump to content
AndyS19

WMI SQL query results object can only be used once

Recommended Posts

I have code that does a WMI SQL query to find all defined printers, and I want to parse the returned object in several places.  However, after parsing it the first time, all other times fail to find any printer objects.

Here is my test code:

test()

Func test()
    Local $oPrinters, $oPrinter, $err, $cnt, $oP, $query

    $query = "SELECT * FROM Win32_Printer"
    $oPrinters = doQuery($query)

    $err = @error
    LogMsg("+++: $err = " & $err & ", isObj($oPrinters) = " & IsObj($oPrinters))

    If ($err == 0) Then

        LogMsg("FIRST LOOP") ; <=== FIRST LOOP
        $cnt = 0
        $oP = $oPrinters
        LogMsg("+++: isObj($oP) = " & IsObj($oP))

        For $oPrinter In $oP
            $cnt += 1
            LogMsg("+++: isObj($oPrinter): " & IsObj($oPrinter) & ", $oPrinter.Name ==>" & $oPrinter.Name & "<==")
        Next
        LogMsg("+++: Found " & $cnt & " printers")

        LogMsg("SECOND LOOP") ; <== SECOND LOOP
        $cnt = 0
        $oP = $oPrinters
        LogMsg("+++: isObj($oP) = " & IsObj($oP))

        For $oPrinter In $oP
            $cnt += 1
            LogMsg("+++: isObj($oPrinter): " & IsObj($oPrinter) & ", $oPrinter.Name ==>" & $oPrinter.Name & "<==")
        Next
        LogMsg("+++: Found " & $cnt & " printers")
    EndIf

EndFunc   ;==>test

Func doQuery($sQuery, $lnum = @ScriptLineNumber)
    #forceref $lnum
    LogMsg("+++:" & $lnum & ": doQuery(" & '"' & $sQuery & '"' & ") entered")
    Local $oWMIService, $oResults, $errstr
    Local $wbemFlags = BitOR(0x20, 0x10) ; $wbemFlagReturnImmediately and wbemFlagForwardOnly

    $oWMIService = ObjGet("winmgmts:\\" & "localhost" & "\root\CIMV2")

    If (IsObj($oWMIService)) Then

        $oResults = $oWMIService.ExecQuery($sQuery, "WQL", $wbemFlags)

        If (IsObj($oResults)) Then
            LogMsg("+++: doQuery() returns @error = 0, Good: returning the object")
            Return (SetError(0, 0, $oResults)) ;;; Good: return the object
        Else
            $errstr = "" _
                     & "WMI Query failed." & @CRLF _
                     & "This is the query:" & @CRLF _
                     & "   " & $sQuery
            LogMsg("+++: ====>" & $errstr & "<===")
            LogMsg("+++: doQuery() returns @error = 1")
            Return (SetError(1, 0, $errstr)) ; Error: Query faled
        EndIf
    Else
        $errstr = "" _
                 & "WMI Output" & @CRLF _
                 & "No WMI Objects Found for class: " & @CRLF _
                 & "Win32_PrinterDriver" & @CRLF _
                 & "using this query:" & @CRLF _
                 & "   " & $sQuery
        LogMsg("+++: ====>" & $errstr & "<===")
        MsgBox(0, "ERROR", $errstr) ; Error: Cannot get $oWMIService object
        Exit (1)
    EndIf
EndFunc   ;==>doQuery

Func LogMsg($msg, $lnum = @ScriptLineNumber)
    ConsoleWrite("+++:" & $lnum & ": " & $msg & @CRLF)
EndFunc   ;==>LogMsg

Parsing the returned $oPrinters object shows 5 printers:

+++:15: FIRST LOOP
+++:18: +++: isObj($oP) = 1
+++:22: +++: isObj($oPrinter): 1, $oPrinter.Name ==>Microsoft XPS Document Writer<==
+++:22: +++: isObj($oPrinter): 1, $oPrinter.Name ==>Microsoft Office Document Image Writer<==
+++:22: +++: isObj($oPrinter): 1, $oPrinter.Name ==>Fax<==
+++:22: +++: isObj($oPrinter): 1, $oPrinter.Name ==>Canon MG7100 series Printer WS<==
+++:22: +++: isObj($oPrinter): 1, $oPrinter.Name ==>Canon MG6100 series Printer WS<==
+++:24: +++: Found 5 printers

Parsing it again, shows no printers:

+++:26: SECOND LOOP
+++:29: +++: isObj($oP) = 1
+++:35: +++: Found 0 printers

 

Share this post


Link to post
Share on other sites

Maybe because the "cursor" is at the end of the resulting record set returned by the query.
You could try to loop throug $oP this way:

For $i = 1 to $oP.count
   ; Process $oP($i)
Next

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2019-10-24 - Version 1.4.14.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2019-07-24 - Version 1.3.6.0) - Download - General Help & Support - Example Scripts - Wiki
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
Task Scheduler (NEW 2019-11-07 - Version 1.3.0.0) - Download - General Help & Support - Wiki

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

When I try the following, 
$cnt = $oP.count

I get this error:
==> The requested action with this object has failed.:

Share this post


Link to post
Share on other sites

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2019-10-24 - Version 1.4.14.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2019-07-24 - Version 1.3.6.0) - Download - General Help & Support - Example Scripts - Wiki
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
Task Scheduler (NEW 2019-11-07 - Version 1.3.0.0) - Download - General Help & Support - Wiki

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Right.  When I set the wbem flags to 0 (wait for complete) and went back to my original code, I was able to make multiple passes of the $oPrinters object.  However, no matter what I tried, I could not access one of the printer objects in $oPrinters using an index, like $oPrinters[2].

So it's fixed, thank you,

Share this post


Link to post
Share on other sites

:)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2019-10-24 - Version 1.4.14.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2019-07-24 - Version 1.3.6.0) - Download - General Help & Support - Example Scripts - Wiki
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
Task Scheduler (NEW 2019-11-07 - Version 1.3.0.0) - Download - General Help & Support - Wiki

Tutorials:
ADO - Wiki

 

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

  • Similar Content

    • 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

    • By TheSaint
      Only early days at this point, but I have been pondering such a program for a while.
      As good as calibre is (thank you Kovid Goyal), which is a great and wonderful ebook suite of tools and a fair database, it does have its limitations. One of which, is how it deals with multiple libraries, another is the views you get. CalibBrowser will seek to address those.
      What CalibBrowser is not going to be, is an editor for existing calibre libraries. That will be left up to calibre, which is very much needed still, and covers many aspects I will never look at. Unlike calibre, which is quite a complex program, CalibBrowser also seeks to be simple. It is mainly a viewer, at this point, but will later be able to create its own libraries. However, it does not and will not export them to calibre, especially as calibre employs a far different method and structure to what CalibBrowser will employ.
      When CalibBrowser starts, it looks for calibre executables and the main Calibre Library. Whatever isn't found, you get prompted for with a browse option.
      A calibre library, is a set of ebook folders (Author\Ebooks) and a database file, always named metadata.db, and which causes an issue when it comes to multiple libraries, but makes life a bit easier when reconstructing any corrupted libraries. However, there are better ways to deal with that, as my program will show.
      The metadata.db file is an SQL database, so I am having a learning curve right now, as I have only ever dealt with an SQL database previously, codewise, when I created my INItoSQL program some time last year, as an exercise to prove a point.
      At the moment, things are pretty basic, and not everything works 100%. Here is a screenshot, to give an idea of it, but keep in mind, I intend to expand the current GUI for other stuff I will be adding.

      Older Screenshots
      Gawd, I just noticed the '3|7' in the Book Input field (original screenshot). I was using that during troubleshooting for the multiple images scrolling and forgot to disable it ... not that it impacts anything. When it comes to maths, I struggle a bit, especially when tired. Right scrolling was easy, with a continuous loop, was easy to implement. Left scrolling was significantly harder for my poor brain ... until I realized I needed to see them as Min and Max.
      As you can see the program is usable, and all the buttons, aside from the Program Information one, work. You can even load different calibre libraries, and even reload after making changes to one with calibre. The calibre program does not need to be running, even to view an ebook in the Calibre Reader. The combo selector for a library and the ADD button are only temporarily placed where they are, until I expand the GUI.
      My intention at this point, is to add another five thumbnail images, directly below existing. Currently they aren't clickable, but I may add that.
      Here is another screenshot, of what you see when you click the larger Cover image.

      If you want to have a play with the program as is, then you will need to also get the 'sqlite3.dll' file from some online source. When CalibBrowser starts successfully with the selected calibre library, it copies its metadata.db file to a sub-folder of the program called 'Backups'. It also creates a sub-folder in that, based on the library name, to house it. That copied file, is the one the program uses, though it does not even edit that, and file modification is checked every time the program starts with a particular library, or when you Reload or select a library. If the original source file has been modified, then the program copy is overwritten. The Reload Database button does nothing, if there is no change detected, and reports such.
      Place the required 'sqlite3.dll' file in the CalibBrowser root folder. Download includes source files (sqlite3.dll excepted).
      Also required of course, is an install of calibre, plus some ebooks in a created library - Calibre Library is the default when you first add ebooks to calibre. The Mobile Read Forums, is a great source for all things ebook, and calibre can be found there in the E-Book Software section.
      CalibBrowser.zip  - Upload 4  (previous downloads: 1 + 12 + 5)
      CalibBrowser (new).zip
      My apologies for the program being created in AutoIt v3.3.0.0. It is the first one I have done in a while, with an older AutoIt version. Basically my Win 7 Netbook, which has a current version of AutoIt, was busy and is always busy doing something, and not suitable for doing big projects for several reasons. My older but more powerful Win XP Laptop, has a better programming environment, better computer chair (most important for my knees etc), better external monitor (wider and newish), full size external keyboard & mouse, and a great suite of setup tools to assist me. I run several older versions of AutoIt already on my Laptop, but haven't yet determined what I need to adjust to add a current version of AutoIt to the mix. This also applies to my hugely beneficial Toolbar For Any program (one of those tools), which I constantly use with SciTE. At some point, when finished, I may update the program to the current AutoIt version ... especially as I believe I am now proficient enough to do so, having become quite familiar with it in the last year or so, making many programs with it.
      Enjoy!
       
    • By Dwalfware
      HI
      Another head scratched
      Anyone solve how to get the IPV6 from WMI?
      I followed the usual SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionID='" & GUICtrlRead($cboAdapters) & "'
      get the index 
      port it to 
      Local $query = $objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index = " & _GetSelectedNIC(), "WQL", 0x30 )
      All i can see is IPv4 addresses
      My question is is there another place the IPv6 information is hiding? I configured my LAN with IPV6 and my wireless with IPv4 so I can see what shows.
      Thanks in Advance.
      PS. I did try google
       
    • By Dwalfware
      Hi Folks
      Can not get my head around this one.
      This function gets the DNS object s
      If you have two DNS entries fine. but if you have only one! Trouble
      $objItem.DNSServerSearchOrder[0] = Primary DNS
      $objItem.DNSServerSearchOrder[1] = Secondry DNS not always there. I need a way to return 0 if not there or the IP if its there.
      Or is there a way to tell how many objects there are in the "[?]"
      I'm terrible at WMI errors, thanks for help in advance.
      Func _GETcurrentNICinfo2() $oErrors = ObjEvent("AutoIt.Error", "Error_Handle") Local $DnsSecondry Local $objWMIService = ObjGet( "winmgmts:\\" & @ComputerName & "\root\CIMV2" ) Local $query = $objWMIService.ExecQuery("SELECT DNSServerSearchOrder FROM Win32_NetworkAdapterConfiguration WHERE Index = " & _GetSelectedNIC(), "WQL", 0x30 ) If @error Then Return 0 If NOT IsObj($query) Then Return 0 Else For $objItem In $query Return $objItem.DNSServerSearchOrder[1] next Endif EndFunc  
    • By amin84
      Hello,
      I'm having trouble getting information from Win32_Processor:
      https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-processor
      How does this WMI Query work? Let's say I need to query VMMonitorModeExtensions, Level, ProcessorId, and ProcessorType.
      How would this work?
      Thanks.
×
×
  • Create New...