Book Image

PowerShell: Automating Administrative Tasks

By : Michael Shepard, Chendrayan Venkatesan, Sherif Talaat, Brenton J.W. Blawat
Book Image

PowerShell: Automating Administrative Tasks

By: Michael Shepard, Chendrayan Venkatesan, Sherif Talaat, Brenton J.W. Blawat

Overview of this book

Are you tired of managing Windows administrative tasks manually and are looking to automate the entire process? If yes, then this is the right course for you. This learning path starts your PowerShell journey and will help you automate the administration of the Windows operating system and applications that run on Windows. It will get you up and running with PowerShell, taking you from the basics of installation to writing scripts and performing web server automation. You will explore the PowerShell environment and discover how to use cmdlets, functions, and scripts to automate Windows systems. The next installment of the course focuses on gaining concrete knowledge of Windows PowerShell scripting to perform professional-level scripting. The techniques here are packed with PowerShell scripts and sample C# code to automate tasks. You will use .NET classes in PowerShell and C# to manage Exchange Online. In the final section, you will delve into real-world examples to learn how to simplify the management of your Windows environment. You will get to grips with PowerShell’s advanced functions and how to most effectively administer your system. This Learning Path combines some of the best that Packt has to offer in one complete, curated package. It includes content from the following Packt products: [*] Getting Started with PowerShell by Michael Shepard [*] Windows PowerShell for .Net Developers Second Edition by Chendrayan Venkatesan and Sherif Talaat [*] Mastering Windows PowerShell Scripting by Brenton J.W. Blawat
Table of Contents (6 chapters)

Chapter 10. WMI and CIM

We've looked at several kinds of cmdlets so far in Module 1, but until now, each cmdlet has been working with a specific kind of object. In this chapter, we will look at the WMI and CIM cmdlets, which will allow us to look at a seemingly unlimited range of object types. In this chapter, we will cover the following topics:

  • What are WMI and CIM?
  • A WMI/CIM glossary
  • Retrieving objects via WMI and CIM
  • Calling methods via WMI and CIM
  • The CDXML modules

What is WMI?

Getting objects from cmdlets is what PowerShell is all about. Unfortunately, there are more kinds of objects that we might be interested in than PowerShell has cmdlets for. This was definitely the case during the time of PowerShell 1.0, which only had less than a hundred cmdlets. What do we do about the objects for which PowerShell doesn't have an explicit cmdlet? The answer involves Windows Management Instrumentation (WMI). WMI was introduced as a common interface to manage operating system objects all the way back in Windows NT. WMI provides a uniform way to retrieve objects, which allows us to inspect and even change the state of components, processes, and other objects. Before we look at specific WMI information, it's important to understand how objects are stored in WMI.

WMI organization

The WMI objects are stored in a repository that is local to a computer system. The repository is divided into several namespaces, each of which provides different objects. Inside a namespace there are the WMI classes, each of which describes a certain type of object. Finally, there are the WMI instances, which are specific examples of a WMI class.

An analogy would help to make more sense of this. If we think of the WMI repository like a filing cabinet, the comparison might go something as follows:

  • The repository is a filing cabinet
  • A namespace is a drawer in the cabinet
  • A class is a folder in the drawer
  • An instance is a piece of paper in the drawer

The information that you want is found on the piece of paper, that is, in the WMI instance.

Finding WMI classes

The first thing to know about the WMI classes is that there are a ton of them. So many, in fact, that you will almost certainly never need to use most of them. As there are so many classes, finding the class that you want to work with can be interesting. The Get-WMIObject cmdlet has a parameter called –List, which lets you get a list of the classes installed on your computer. Combining this cmdlet with Measure-Object shows that my computer (Windows 7) has over a thousand classes in the default namespace:

Finding WMI classes

You clearly don't want to look through a list of so many items, so you can narrow down the list with the –Class parameter, which accepts wildcards. For instance, to find classes that deal with the processor, you might do this:

Finding WMI classes

The first two in the list (CIM_Processor and Win32_Processor) are the results that are most useful in this case. Depending on what wildcard you use, you may need to look at several classes to find the one that is most appropriate.

Tip

The classes beginning with Win32 are based on the classes beginning with CIM. Generally, I stick with the Win32 classes, but they usually have almost the same information.

Retrieving objects with Get-WMIObject

If you know the name of a class and what namespace that class belongs to, it is simple to retrieve the class using the Get-WMIObject cmdlet. For instance, there is a class that describes the installed operating system called Win32_OperatingSystem contained in the default (root\CIMV2) namespace. To retrieve this class, either of these command-lines will work:

Get-WMIObject –class Win32_OperatingSystem
Get-WMIObject –class Win32_OperatingSystem –namespace root\CIMV2
Retrieving objects with Get-WMIObject

The output here is formatted, so you will probably want to use Select-Object –property * to see all the properties. In this case, there are 73 properties, which are too many for a screenshot.

Tip

You try it!

Use Get-WMIObject with the Win32_OperatingSystem class and look through the properties. You might make a note of the properties that you think would be useful. As you use WMI (and CIM) more and more, you will find a number of classes and properties that you will come back to over and over again. Hence, having a list of "favorites" can be a real life-saver.

One thing you probably noticed with Win32_OperatingSystem is that only one object (instance) was retrieved by the cmdlet. This makes sense, because there's only one operating system running on a computer at a time (not counting VMs, of course). The other classes might return zero, one, or any number of instances.

A class that should be easy to understand is the Win32_Service class. This class represents the Windows services that are installed in your operating system. You can see the beginning of the formatted output in the following screenshot:

Retrieving objects with Get-WMIObject

You might ask why we would use WMI to get information about services when we have a perfectly good cmdlet (Get-Service) that is designed to do this. Even though we can see only a few properties of each WMI service object in the preceding output, theres enough information to illustrate an important point. The first object in the output, AdobeARMService, shows six properties. Comparing these properties with the full output of the Get-Service cmdlet reveals that the Name and State properties of the WMI object have analogous properties (Name and Status) in the Get-Service object, but the other four properties (including ProcessID) are missing from Get-Service:

Retrieving objects with Get-WMIObject

Remember that WMI is a very mature technology that has been in use for over 20 years. As WMI is so well established, most aspects of the Windows ecosystem is covered very well by WMI.

Tip

Tip!

In addition to keeping track of the interesting WMI classes, you might also want to make a note of the properties of WMI instances that are missing from the objects output by other PowerShell cmdlets. Often, WMI provides the easiest way to get some information.

Getting the right instance

With Win32_ComputerSystem, we didn't have to worry about which instance was returned because there was only one. The next class we looked at was Win32_Service, which returned multiple objects, one for each service on the computer. In order to select specific instances, we can use the –Filter parameter.

Since WMI covers thousands of different kinds of classes, it would be impossible for Get-WMIObject to have specific parameters to help us narrow down which objects we would like to see. For instance, if we use Get-Service to look at services, we can use the –Name parameter to filter by name. Not all WMI objects have a name property, so it wouldn't make sense to have a parameter to filter by this single property. The solution is to have a query language called WMI Query Language (WQL), similar to SQL, and a single parameter called –Filter that takes the WHERE clause of the WQL query in order to filter the objects.

WQL syntax

WQL syntax is very simple to use, and is very similar to SQL. In the WQL filter, you can use the property names of classes, constants, and operators to build the conditions you are looking for. For example, to return only the AdobeARMService instance from the Win32_Service class, you could use a filter of "Name='AdobeARMService'". Note that I have used double quotes around the filter and single quotes around the string value of the Name property. The full Get-WMIObject statement and output looks as follows:

WQL syntax

Filters can be more complex as well. Consider the Win32_LogicalDisk class, which contains an instance for each drive on the local computer:

WQL syntax

If we wanted to list all the drives that had less than 10GB free and didn't care about the removable, we could use a filter as follows:

 -Filter "DriveType=3 and FreeSpace< 10737418240"
WQL syntax

Here, you can see that I have calculated the value of 10GB because WQL doesn't understand units, and also, I have used a variable to hold the filter in order to keep the line shorter.

Tip

Although WQL filters look like SQL syntax, there are crucial differences. You can use comparison operators (=, <>, >, <. <=, >=, LIKE) in the expressions and can link multiple expressions together with AND and OR. You can also group expressions using parentheses. Another important thing to remember is that the WQL strings use backslash as the escape character. For more details, including how to use the WQL queries, refer to the About_WQL help topic.

Getting the right instance

With Win32_ComputerSystem, we didn't have to worry about which instance was returned because there was only one. The next class we looked at was Win32_Service, which returned multiple objects, one for each service on the computer. In order to select specific instances, we can use the –Filter parameter.

Since WMI covers thousands of different kinds of classes, it would be impossible for Get-WMIObject to have specific parameters to help us narrow down which objects we would like to see. For instance, if we use Get-Service to look at services, we can use the –Name parameter to filter by name. Not all WMI objects have a name property, so it wouldn't make sense to have a parameter to filter by this single property. The solution is to have a query language called WMI Query Language (WQL), similar to SQL, and a single parameter called –Filter that takes the WHERE clause of the WQL query in order to filter the objects.

WQL syntax

WQL syntax is very simple to use, and is very similar to SQL. In the WQL filter, you can use the property names of classes, constants, and operators to build the conditions you are looking for. For example, to return only the AdobeARMService instance from the Win32_Service class, you could use a filter of "Name='AdobeARMService'". Note that I have used double quotes around the filter and single quotes around the string value of the Name property. The full Get-WMIObject statement and output looks as follows:

WQL syntax

Filters can be more complex as well. Consider the Win32_LogicalDisk class, which contains an instance for each drive on the local computer:

WQL syntax

If we wanted to list all the drives that had less than 10GB free and didn't care about the removable, we could use a filter as follows:

 -Filter "DriveType=3 and FreeSpace< 10737418240"
WQL syntax

Here, you can see that I have calculated the value of 10GB because WQL doesn't understand units, and also, I have used a variable to hold the filter in order to keep the line shorter.

Tip

Although WQL filters look like SQL syntax, there are crucial differences. You can use comparison operators (=, <>, >, <. <=, >=, LIKE) in the expressions and can link multiple expressions together with AND and OR. You can also group expressions using parentheses. Another important thing to remember is that the WQL strings use backslash as the escape character. For more details, including how to use the WQL queries, refer to the About_WQL help topic.

WQL syntax

WQL syntax is very simple to use, and is very similar to SQL. In the WQL filter, you can use the property names of classes, constants, and operators to build the conditions you are looking for. For example, to return only the AdobeARMService instance from the Win32_Service class, you could use a filter of "Name='AdobeARMService'". Note that I have used double quotes around the filter and single quotes around the string value of the Name property. The full Get-WMIObject statement and output looks as follows:

WQL syntax

Filters can be more complex as well. Consider the Win32_LogicalDisk class, which contains an instance for each drive on the local computer:

WQL syntax

If we wanted to list all the drives that had less than 10GB free and didn't care about the removable, we could use a filter as follows:

 -Filter "DriveType=3 and FreeSpace< 10737418240"
WQL syntax

Here, you can see that I have calculated the value of 10GB because WQL doesn't understand units, and also, I have used a variable to hold the filter in order to keep the line shorter.

Tip

Although WQL filters look like SQL syntax, there are crucial differences. You can use comparison operators (=, <>, >, <. <=, >=, LIKE) in the expressions and can link multiple expressions together with AND and OR. You can also group expressions using parentheses. Another important thing to remember is that the WQL strings use backslash as the escape character. For more details, including how to use the WQL queries, refer to the About_WQL help topic.

Calling methods

When dealing with WMI, there are two kinds of methods that come into play, instance methods and class methods. Calling the WMI instance methods is similar to calling methods on any PowerShell object, that is, using dot-notation. For instance, WMI objects from the Win32_Service class have a StartService() method defined in them, which we can verify using Get-Member:

Calling methods

To call this method, we can store the instance in a variable and use the variable to call the method. Note that the method outputs a structured result type. The ReturnValue property of the output gives us the outcome of the operation. A value of zero means success. An example of a successful method invocation can be seen in the following screenshot:

Calling methods

Tip

You might notice that the preceding screenshot is an elevated session. If you try to start a service in a non-elevated session, you get a ReturnValue of 2, which means "warning".

WMI and CIM

PowerShell 3.0 introduced the Common Information Model (CIM) cmdlets to access WMI repositories. The WMI cmdlets are still present, but they have been superseded by the CIM cmdlets that can perform all the same functions. From a functional level, the CIM cmdlets are similar to the WMI cmdlets. The main difference is the communication that the cmdlets perform with the target computer. The WMI cmdlets use the DCOM protocol, which is a pretty standard thing to do on Windows systems, especially 20 years ago when WMI was created. Unfortunately, DCOM is kind of a mess from a firewall standpoint, as it uses a range of ports (over 16000 ports by default) that need to be open in order to function. In a data center situation, requiring this many ports to be opened in the firewalls is something that network engineers frown upon.

The CIM cmdlets, by default, use Web Services for Management (WS-MAN), the protocol that PowerShell remoting is based on. WS-MAN uses a single port, and has a number of other properties that make it ideal from a networking standpoint. Finally, the CIM cmdlets support sessions, which allow you to reuse a connection to a computer or a set of computers for multiple requests, which can dramatically reduce the network traffic for some workloads.

If you're just looking at the WMI repositories on the local box like we've done in the examples of this chapter, both sets of cmdlets will work fine. If you're looking at the WMI classes across multiple computers in a network, you will need to consider firewall rules and whether WS-MAN is enabled. These are beyond the scope of Module 1, please see Module 2 and 3 for more, but are good to make a note of.

The CIM cmdlets

The two main CIM cmdlets that you will use are Get-CIMClass and Get-CIMInstance. Although Get-WMIObject is used to retrieve both the WMI classes (with –List) and WMI instances (without –List), these roles are carried out by separate CIM cmdlets. Using Get-CIMClass is virtually identical to using Get-WMIObject with the -List switch. We can recreate the processor example from earlier in the chapter with Get-CIMClass as follows:

The CIM cmdlets

Retrieving instances is done, of course, with Get-CIMInstance. Filters work exactly like they do with Get-WMIObject. Also, the objects output by these two cmdlets are the same, so working with the results will be exactly the same.

The CIM cmdlets

The two main CIM cmdlets that you will use are Get-CIMClass and Get-CIMInstance. Although Get-WMIObject is used to retrieve both the WMI classes (with –List) and WMI instances (without –List), these roles are carried out by separate CIM cmdlets. Using Get-CIMClass is virtually identical to using Get-WMIObject with the -List switch. We can recreate the processor example from earlier in the chapter with Get-CIMClass as follows:

The CIM cmdlets

Retrieving instances is done, of course, with Get-CIMInstance. Filters work exactly like they do with Get-WMIObject. Also, the objects output by these two cmdlets are the same, so working with the results will be exactly the same.

CDXML modules

One of the drawbacks of using the WMI or CIM cmdlets is that you don't get to use parameters that are specific to the properties of the WMI class you are dealing with. For instance, when we looked at the Win32_LogicalDisk instances, it would have been really nice to have parameters such as DriveType or Name to easily filter the output without having to use a WQL filter statement. In PowerShell 3.0, the concept of a CDXML module was introduced. CDXML modules allow you to create an XML description of the cmdlets and the associated parameters dealing with a WMI class, and the PowerShell engine creates the cmdlets for you when you import the module.

The CDXML modules have two main advantages, as follows:

  • The module is XML, so no coding is necessary.
  • End users get to use parameters that are specific to the type of object rather than a generic –Filter parameter

In PowerShell 4.0, the majority of modules on a server will be CDXML modules, because they are easy to write.

Summary

In this chapter, we have taken a quick look at the basics of using the WMI and CIM cmdlets. It should be clear that there is a lot of information in the WMI repository, and these cmdlets are essential tools for PowerShell scripters. With the introduction of CDXML modules, we're also seeing more cmdlets that are customized to specific WMI classes, making their usage even easier.

In the final chapter, we will look at administering Internet Information Services (IIS).

For further reading