WMI

Network WMI queries

I have already covered searching AD and running a WMI query on remote computers. It is easy to combine the two for a flexible tool that can run the same query on all computers that meet a certain criteria.

To achieve this I wrote the function adwmiquery. It does a lot considering it is only really 4 lines of code.

I originally wanted to see the amount of free space of all the drive on all of the servers. This is still the default behavior if you just run the netquery.py directly. As an added bonus you can run any wmi query against all servers simply by entering the select statement on the command line as so.

python netquery.py Select Name,DriverName,PortName From Win32_Printer

The function takes 3 optional arguments as follows
WMI Query: self explanatory (defaults to drive space)
AD Query: specifies the computers to run the WMI Query on (defaults to servers)
Filter Function: a function which gets the result of the WMI query

The last argument is a function that accepts two arguments, the name of the computer and the result of the WMI query as a list. This can be used to format the output or store the result. You can also use this to add additional filtering, maybe you only want to see drives with less than 10% free space.

As an example the following lists all printers on the server (so used the default AD query) and writes them to a CSV file.

import csv,sys

# if netquery.py is not in you path you need the following line
# sys.path.append(r"C:\Path\To\File")
from netquery import adwmiquery

with open(r"C:\Temp\printers.csv","w") as csvfile:
    out = csv.writer(csvfile)
    out.writerow(['Server','Printer Name','Driver (Make & Model','Port'])

    def prnwrite ( compname , prnlist ):
        "writes the printer details to the CSV file"
        for prn in prnlist:
            out.writerow([compname,prn.Name,prn.DriverName,prn.PortName])

    # run the wmi query on all servers (default) using above fn to output to csv
    adwmiquery(wql = "Select Name,DriverName,PortName From Win32_Printer",
               filterfn = prnwrite)
Advertisements

Another WMI tool

Having not so long ago wrote the post about WMI Code Creator I find there is another Microsoft tool called Scriptomatic 2 that does a very similar job and lists Python as a supports language. Again the download just extracts to a runnable file so no installer needed. My only issue was that it’s an hta file rather an executable and needs to be run an an administrator.

The screen layout is a little more efficient (click on the thumbnailScriptomatic 2 showing the processor usage on the right to get a full sized image). The Namespace defaults to root\CIMV2 and you can select the class from the drop down list the same as Code Creator.

The languages supported does include Python but uses win32com.client directly and produces a massive amount of code to do what my previous post did in 5 lines. Still you can just copy the WQL query and use it in your code.

What Scriptomatic gives you that Code Creator doesn’t the ability to run the WMI query and export it. Simply select the output format on the right and click Run. You may want to set the language to VBScript if you have problems. Also by changing the Target Computers list at the bottom you can query other computers rather than just the local one.

WMI explored

The biggest hurdle to using WMI I found was knowing where the information you want is stored. There are various browsers available but one quick and simple entry point is Microsoft’s WMI Code Creator. It extracts to an runnable executable so no installer needed. While it is designed for VB and C# users, if you ignore most of the code it creates and just grab WQL statement I found it one of the quickest ways of getting up and running.

What lead to code creator was a need to monitor the process usage. I suspected correctly I could get this information from the WMI but had no idea how.

Starting WMI Code Creator and using the default namespace of root\CIMV2 you can use the drop down list of classes to browse what is available. The first one I tried was Win32_Processor. Selecting the class gives you the properties. Select the properties (I just select every one) and clicking Search for Property Values gives you a list of the values. Needless to say Win32_Processor gives you the processors installed, not quite what I want.

Next class to try is the long winded Win32_PerfFormatteThe WMI Code Creator in usedData_PerfOS_Processor. This looked more promising, as the thumbnail to the right shows (click for larger image). Getting the properties values brought back far more data than I expected and a slight surprise; I had forgot I had a dual core processor.

Because I have more than one core, the query returns 3 sets of data, one for each processor and a total. WMI Code Creator indents the even sets which helps a little but there are better methods.

The code created in the right hand pane is of little use in Python but you can copy and paste the WQL query to save some time. Time to get this query into Python so we can have a play.

import wmi
mywmi = wmi.WMI()
wql = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor"
for item in mywmi.query(wql):
    print(item)

Wow, that’s a lot of information. At this point the documentation comes to the rescue (enter the class name into a search engine). It looks like PercentProcessorTime is the property I need. So with a quick update gives me a very crude processor monitor

import wmi, time
mywmi = wmi.WMI()
wql = 'SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = "_Total"'
while True:
    for item in mywmi.query(wql):
        print(item.PercentProcessorTime)
    time.sleep(1)

Accessing WMI on other machines

Another admin here has been using PowerShell to check services running on a group of servers and restart them if they have stopped. Not wanting to learn PowerShell just for this I decided to have a go at writing the same script in Python.

Again Tim Golden allows the process to be simplified a little with his WMI module. There is a windows installer for this one which hides all the installation.

To access a remote server rather than your local computer just pass the servername as a parameter to the WMI function. A list of services is obtained from Win32_Service() and rest is fairly straight forward.

I created an example script which goes through a list of servers and compares all theĀ  services against a tuple of services I am interested in for any that have stopped. If it finds any it prints out the server number and the service caption before trying to start the server again.

I’ve not bothered with authorisation, the script would need to be run under a user account with the necessary privileges. The script is also not optimised, I might come back to this at a later date.