Connecting to WMI with PHP

WMI (Windows Management Instrumentation) is a very powerful tool for anyone who runs their own server on a win32 platform. It can provide you with many pieces of information that you’d never thought possible. Beyond that you can even control almost every aspect of your system with WMI. Couple that with PHP and you’ll have the power to perform almost any type of action you’d like on your server.

Contributed by
Rating: 3 stars3 stars3 stars3 stars3 stars / 27
July 06, 2004
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Getting Started

WMI uses the Common Information Model, which is an industry standard to represent systems, applications, networks, devices, and other components. This means that you can have it show all kinds of useful information such as what programs are running, how much ram is being used, network activity, even how many hard drives are installed on your system. Almost every Windows system since Windows 2000 has WMI capabilities, and it can be downloaded for earlier systems from Microsoft’s website. All you have to do to turn it on is open a command prompt then execute the command “WMIC”. It will take a few minutes to start if you’ve never used WMI on your system before because it has to install all the services needed to run WMI.

It would seem fairly simple to just run an exec() in PHP and retrieve whatever data you wanted to from the command line, but it’s not exactly that easy. The first thing to do is figure out exactly what information you want, and what you want to do with it. Then you’ll have to figure out the best way to make WMI format your information. And lastly you’ll have to get PHP to send the query to the WMI, retrieve the data, and output it in a way that will be organized and easy to understand. You’ll also want to do a little more research on WMI before you get started. I recommend the Microsoft Developer Network’s website on WMI, which can be found here http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp

The Newest SQL Slang

SQL has been around for a long time, but now there’s a newer query language called WQL. WQL stands for WMI Query Language, and I bet you can guess what it’s used for. WQL isn’t hard to learn at all. The hard part is getting used to how much it seems like SQL while it’s not SQL at all. WQL is actually a subset of SQL with minor changes so that it will work with WMI. A table containing all the keywords that work with WQL can be found here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/sql_for_wmi.asp
After you get comfortable with WQL, we’ll start talking about how to find out what information is available from the WMI.

The easiest way I’ve actually found to list the available information provided by WMI is to open a command prompt and type in “wmic”. This will launch the command line interface to WMI. After the wmic has started type in a simple /? and it will list out all the available aliases that you can use. If you then type in the name of one of the aliases at the wmic command prompt, it will then show you all the information that can be gathered from that particular alias.  For example if you type in “CPU” at the prompt it will show you a table that contains all the data about the CPU, such as the address width, the architecture, the caption name and so on. This information isn’t very important to most people, so what we’ll want to do is use a little bit of WQL to get some useful information. If you go back to the command prompt and type in “CPU get LoadPercentage” ,it will show a little table with only the current load percentage in it.

The most useful aliases I’ve found in WMI are OS, CPU, and LOGICALDISK. Here are some examples of WQL for these.

This one will get the amount of free RAM, total RAM, free virtual memory, and total virtual memory, and return the value’s in bytes.

os get FreePhysicalMemory,TotalVirtualMemorySize,
FreeVirtualMemory,TotalVisibleMemorySize

This returns the current CPU load in a percentage.

cpu get loadpercentage

This one will return the total size the name, and the free space in byte for each hard drive partition on your system.

logicaldisk where drivetype=3 get size,name,freespace

Now that we’ve talked about how to get some information, let’s talk about how to get our data formatted for use with PHP.

The Safe Command Line “format” Command

This is by far the most useful part of WMI in all my experience with it. By default the data returned by the WMI is dynamically tab delimited, which means you never really know how many tabs or spaces that it’s going to have between your data. So what we want to do is take a look at the /format switch for the WQL. /format lets us specify a XSL file that contains formatting instructions. XSL is an XML Stylesheet that is commonly used to format data into a more readable form, usually XML. But for sake of this article we’ll (of course) be using it to format our WMI data. The first thing you need to know about your formatting files is that they are stored in a folder named wbem which can be found in your system32 folder. They have a few that you can use and edit already made; the only ones that I found that are useful for passing data to PHP are the RAWXML and the CSV formats. The CSV format is comma delimited so that you can load all the data into an array and parse it out. The RAWXML format is nice if you want to parse the data like XML.

I like to use the data formatted as XML because I can output the data easily with simpleXML, which is part of PHP5. There were a few problems using the RAWXML style that is packaged with Windows because it didn’t output it in a very useful or organized fashion -- well, not well enough my taste. So I quickly hacked my way through the RAWXML style to make my own style. I don’t personally know much about XSL, but I found that it wasn’t very hard to create my own style from editing one of the default one’s. Here’s the one I came up with.

<?xml version="1.0"?>

<!-- Copyright (c) Microsoft Corporation.  All rights reserved. -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="RESULTS">

<xsl:for-each select="CIM/INSTANCE">

<xsl:sort select="PROPERTY[@NAME='Name']|PROPERTY.ARRAY[@NAME='Name']|PROPERTY.REFERENCE[@NAME='name']"/>

<xsl:for-each select="PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE">

<xsl:variable name="typevar" select="@TYPE"/>

<xsl:copy><xsl:value-of select="@NAME"/></xsl:copy>

<xsl:for-each select="VALUE|VALUE.ARRAY|VALUE.REFERENCE">

<xsl:apply-templates select=".">

<xsl:with-param name="type">

<xsl:value-of select="$typevar"/>

</xsl:with-param>

</xsl:apply-templates>

</xsl:for-each>

</xsl:for-each>

</xsl:for-each>

</xsl:template>

 

<xsl:template match="VALUE">

<xsl:param name="type"/>

<xsl:param name="includequotes"/>

<xsl:param name="isarray"/>

<xsl:choose>

<xsl:when test="$type='string'">

<xsl:if test="$includequotes='true'">"</xsl:if><xsl:copy><xsl:value-of select="."/></xsl:copy><xsl:if test="$includequotes='true'">"</xsl:if>

</xsl:when>

<xsl:when test="$type='char16'">

<xsl:copy><xsl:value-of select="."/></xsl:copy>

</xsl:when>

<xsl:when test="$type='uint16'or $type='uint32' or $type='uint64' or $type='uint8' or $type='real32'or $type='real64' or $type='sint16'or $type='sint32' or $type='sint64' or $type='sint8'">

<xsl:if test="not($isarray='true')"><xsl:copy><xsl:value-of select="."/></xsl:copy></xsl:if>

</xsl:when>

<xsl:otherwise>

<xsl:copy><xsl:value-of select="."/></xsl:copy>

</xsl:otherwise>

</xsl:choose>

</xsl:template>

 

 

<xsl:template match="/" >

<element>

<xsl:apply-templates select="COMMAND/RESULTS"/>

</element>

</xsl:template>

</xsl:stylesheet>

This will output your data in a really clean XML format with the name of the property in the <property></property> tags and the value of it in the <value></value> tags. Here is the output after running a query to get the freephysicalmemory and the freevirtualmemory:

<?xml version=”1.0” encoding=”UTF-16”?> <element><property>FreePhysicalMemory</property><value>513128
</value></element><element><property>FreeVirtualMemory</property>
<value>2708708</value></element>

Now, here’s an example of the same thing with the CSV format

Node,FreePhysicalMemory,FreeVirtualMemory

NS1,513128,2712180

As you can see, the XML is a lot easier to work with because of how I’ve grouped the names and values, unlike the CSV, not to mention it can easily be parsed with simpleXML.

Spit it Out

Now, here’s something that’s interesting to know -- you can’t use the exec function to work with WMI, it won’t output. Instead you have to use the passthru function. This is because the passthru function runs the program and returns the raw output. Exec doesn’t do that, however you can use passthru in the exact same way you use exec so you don’t really need to worry about anything. To simply send your information to the browser all you’ll have to do is this.

echo passthru('wmic cpu get loadpercentage /format:newxml');

That’s it, no big deal, right!? Well, no, that’s not really it. That will work if you want to look at the source of the page every time to see the data, which I don’t think you’d want to do -- you’ll have to make it parse the data with an XML parser or simpleXML. I prefer simpleXML because it’s, well, simple. So I came up with the small little function: 

function parse_stat($instance){

ob_start();

passthru('wmic '.$instance.' /format:newxml');

$results=ob_get_clean();

$xml[] = simplexml_load_string($results)

Return $xml;

}

This will return an array of all my WMI data which I can then put in a foreach loop and echo out, where I want it. This function is also fairly nice because you only have to tell it the WQL string, no formatting data. This is how it’s used.

parse_stat("os get FreePhysicalMemory,TotalVirtualMemorySize,FreeVirtualMemory,
TotalVisibleMemorySize");

parse_stat("cpu get loadpercentage");

parse_stat("logicaldisk where drivetype=3 get size,name,freespace");

foreach ($xml as $wmi){

echo $wmi->property.”: “.$wmi->value;

}

And that is just about all you need to know to get started working with WMI from PHP.

Just a Few More Words

Everyone who plans to use WMI on any project, not just projects dealing with PHP, needs to be aware of the security risk that WMI can present. WMI is a very powerful tool. You can change critical system information with WMI. If someone has access to your WMI scripts, you should make sure that they are someone you trust with not only your source code but your entire system, because with WMI that’s basically what they have, your entire system.

I’d suggest only using WMI if it’s a must. If you use WMI in an open environment that can receive outside connections, make absolutely sure that it can’t be accessed by the public. If you're making a script that can be accessed by the public, make sure that there’s no possible way for them to edit or change the WQL in anyway. I cannot stress this enough. WMI can be used to do as much as changing your desktop wallpaper, all the way to editing hardware information, and in some rare cases the BIOS can even be controlled, and the system can be shutdown.

Before you begin a project with WMI, take note of any security risks that may be involved and deal with them in the proper ways.

blog comments powered by Disqus
WINDOWS SCRIPTING ARTICLES

- More Windows Scripting Workarounds from Nilpo
- Overloading Methods and More in VBScript
- Improving MFC for Windows Vista
- Regular Expressions in VBScript
- Working with Dates in WMI
- Completing Calendars with VBScript Date Func...
- Building Calendars with VBScript Date Functi...
- Working With Dates and Times in VBScript
- Designing WCF DataContract Classes Using the...
- Understanding Dates and Times in VBScript
- Working With Arrays in VBScript
- Compressed Folders in WSH
- Using .NET Interops in VBScript
- Nilpo`s Scripting Secrets, Vol I
- Database operations using Silverlight 2.0 WC...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 3 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials