One of the most useful jobs for PowerShell is to create a bank of WMI based scripts. Furthermore, scripting WMI with PowerShell is much easier and more efficient than using the combination of VBScript
and WMI.
Skills that you develop through experimenting with PowerShell and WMI will help you manage your Exchange 2007 server. With practice, you will also be able to adapt these techniques to Active Directory and Longhorn.
My point is that while
PowerShell is clearly has a future, you can get started here and now by creating WMI cmdlets.
To appreciate the beauty of a crystal, you should examine the facets from different angles. The same applies to the diamond that is WMI; I recommend that to gain perspective we
investigate WMI from these five angles.
Imagine WMI as a database, which keeps information about a computer's components such as the: BIOS, services and network settings.
Regard WMI as a method for collecting data about a machine's hardware and software.
View WMI as a pipe, which magically connects to the core of any Microsoft operating system (post 2000).
Think of WMI as a having its own PowerShell dialect, for example the WQL select clause.
Treat WMI as a microscope, and use it to probe
the operating system's objects and their properties.
Whenever I think about WMI for any length of time, it hits me: the operating system must know everything that's going on! Therefore, as long the PowerShell script has sufficient rights, it can use
WMI and tap into that vast fountain of operating system knowledge. Windows Server 2003 must know 'stuff' such as how much memory each process is using, how much free space there is on each partition,
which devices are on which Bus. It is even possible to manipulate or 'set' values on some of these properties and thus achieve configuration via scripts rather than GUIs.
For me, my interest in PowerShell took off when I discovered this command: get-WmiObject win32_computersystem
The result was:
Domain : cp.mosel Manufacturer : VIAK8T Model : AWRDACPI Name : BIG-SERVER PrimaryOwnerName : Guy TotalPhysicalMemory : 2146910208
I was curious to discover what other WMI Objects were available for scripting; then I remembered the -list switch from another PowerShell command (get-Eventlog -list). Thus I tried: get-WmiObject -list
Next, I redirected the output from the screen to a file by appending 'out-File': out-File WmiObject.txt. To make:
get-WmiObject -list | out-File WmiObject.txt
My next problem was the list was
too long, therefore I added a 'Where' filter
Note 1: The tiny backtick (`) tells PowerShell that the command
continues on the next line.
Note 2: On other pages I use plain 'Where', or even '?' instead of the full 'Where-Object'.
Note 3: I expect you have guessed that PowerShell commands are case insensitive. At present I am not sure which
is best, WmiObject, wmiObject or WmiObject - they all produce the same results. Another minor point,
since the verb 'get' is the default, you can shorten the command to: WmiObject
win32_computersystem. Or if you like aliases: gwmi win32_computersystem.
Guy Recommends: SolarWinds Engineer's Toolset v10
The Engineer's Toolset v10 provides a
comprehensive console of utilities for troubleshooting computer problems. Guy says
it helps me monitor what's occurring on the network, and the tools
teaches me more about how the system literally operates.
There are so many good gadgets, it's like having free rein of a
sweetshop. Thankfully the utilities are displayed logically: monitoring, discovery, diagnostic, and Cisco tools.
Download your copy of the Engineer's Toolset v 10
Wouldn't it be useful to get a list of all the
properties on a PowerShell object? The answer is get-Member. Here is an example of applying the get-Member command to examine the Win32_Logical Disk:
Example 1
get-WmiObject win32_LogicalDisk | get-Member
Sample Output (Heavily truncated)
get-WmiObject win32_LogicalDisk | get-Member
Example 2
Here is another example, this time PowerShell interrogates the WMI BIOS property list:
When I am in 'let us get started' mode, I gloss over the optional PowerShell commands.
However, when we need to troubleshoot, then the secret of success is knowledge of a command's parameters. To reveal the full list of parameter, let's call for help:
When you employ get-Wmiobject the first thing you want to specify is the class of the object, for example: Win32_LogicalDisk. If this class name
follows directly after get-Wmiobject there is no need to explicitly use the -class parameter. PowerShell assumes from the first position that the word defines the type of class you wish to script.
The reason that the -namespace parameter is optional because Wmiobject has a default value of: root\cimv2. Thus the time to include
this parameter is when you wish to use a different namespace, such as: root\directory\ldap.
Note 1: Interestingly, when you explicitly define the namespace, the command displays more properties, than if
you omit the parameter and rely on the default.
As expected, when you use get-Wmiobject PowerShell defaults to the current machine; unlike
VBScript, you don't have to add "." However, if you want to run the script against another machine you need
to add the -computerName parameter. Incidentally, the target machine must have WMI, but does not need PowerShell. As all Microsoft Computers after Windows 2000 have WMI, there should be no
problem; your only real concern could be firewalls. Knowledge of the -computerName parameter helps when you want a script which loops through multiple hostnames, or IP addresses.
Note 1: If you would like to run my cmdlet on your network, then please
amend 'bigserver' to the name of a real machine on your subnet.
Note 2: To cope with word-wrap I added the tiny backtick ` command. This tells PowerShell that there is one command but
it is split over two lines.
Note 3: As far as I can see, the shorter -computer works just as well as the longer -computerName. In fact, this is an example of
PowerShell's intelligence, as soon as the word that you are typing becomes unique, then PowerShell automatically fills in the missing letters. To see what I mean try -comput, or even -comp.
Guy Recommends: SolarWinds LANSurveyor
LANSurveyor will produce a neat diagram of your network topology. But that's
just the start;
LANSurveyor can
create an inventory of the hardware and software
of your machines and network devices. Other neat features include dynamic
update for when you add new devices to your network. I also love the ability to export
the diagrams
to Microsoft Visio.
Finally, Guy bets that if you take a free trial of LANSurveyor then you will
find a device on your network that you had forgotten about, or someone else
installed without you realizing!
To illustrate the -filter parameter, let us set the scene: you wish to interrogate the logical disk, but you only want information about the 'c:' drive.
Incidentally, -filter is much easier than comparable constructions in VBScript.
Note 1: Pay close attention to the quotes. One set of double quotes surrounding "Device ID = ".
And one set of single quotes around the disk drive 'c:'.
Note 2: PowerShell's usual comparison operators employ -eq. However, here -filter requires the equals sign.
Note 3:
To concentrate on the main feature -filter, I omitted the optional parameters that we covered previously.
In this example, imagine that we need information
about the hard disk, but we don't want the results cluttered with data about floppy drives, CD or DVD drives. If you are familiar with any dialect of SQL you may recognise the select statement below:
get-WmiObject -query "select * from Win32_LogicalDisk where DriveType ='3' "
Note 1: As with -filter, you need to be careful with syntax of the -query parameter. Observe the quotes,
and how I have separated the single quote from the double quote with a space: = '3' ". In fact, as 3 is a numeric value, we could remove these single quotes and simplify the expression to: where
DriveType = 3.
Let us kill two birds with one stone. Firstly,
I want to introduce variables and
secondly, I want to filter the properties for a WMI Object. This is the idea, let us set a variable called $disk equal to get-WmiObject Win32LogicalDisk. Now we can call individual properties, for example
$disk.Name, or $disk.Size.
There is one additional script structure we must master, the foreach construction. Since there is more than one drive we need the foreach loop below. Observe how this
construction requires a placeholder ($drive in $disk).
To recap,
we begin with the variable $disk. We set its value = get-WmiObject Win32_LogicalDisk. We want to display the name $drive.Name and the size $drive.Size. Because the raw disk size is in bytes,
we best convert to gigaabytes (GB), thus we need to divide by 1024 x 1024 x 1024 (1073741824). [int] displays the number as an integer.
With the brackets it is always worth paying attention to detail. PowerShell
is particular about the style of bracket, for example {Int} or even (int) draw an 'unexpected token' error message. Equally, the foreach construction needs the simple elliptical brackets (), while the
properties are encased in curly {} brackets.
Get-WmiObject is a good bellwether for PowerShell. Contrast the
ease with which PowerShell displays WMI objects, with the struggle which VBScript achieves the same result. I say ease of PowerShell, there is still plenty to learn about brackets, variables and foreach
loops. My advice is begin learning PowerShell by experimenting with a simple object such as 'Process' or 'Eventlog' before tackling the WmiObject family of objects.
Please write in if you see errors of any kind. Please report any factual mistakes, grammatical errors or broken links, I will be happy to not only to correct the fault, but also to give you credit.
Guy
Recommends: Orion's NPM - Network Performance Monitor
Orion's performance monitor is designed for detecting network outages.
A network-centric
view make it easy to see what's working, and what needs your attention.
This utility guides you through troubleshooting by indicating whether the
root cause is faulty equipment or resource overload.