Quantcast
Channel: Hey, Scripting Guy! Blog
Viewing all articles
Browse latest Browse all 3333

Hey, Dude! Where Are My Methods?

$
0
0

Summary: Windows PowerShell MVP, Richard Siddaway, talks about WMI's missing methods in Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have a guest blog post by Windows PowerShell MVP, Richard Siddaway.

Richard has been working with Microsoft technologies for 25 years and has spent time in most  IT roles, including analyst-programmer, server administrator, support, DBA, and architect. He has been interested in automation techniques (including automating job creation and submission on main frames many years ago). He originally used VBScript and WMI since it became available on Windows NT 4.0. Windows PowerShell caught his interest during the early beta versions in 2005. 

Richard blogs extensively about Windows PowerShell and founded the UK Windows PowerShell User Group in 2007. A Windows PowerShell MVP for the last six years, Richard has given numerous talks on Windows PowerShell at various events in the UK, Europe, and the USA. He is frequent speaker for Windows PowerShell User Groups worldwide.

He has published a number of posts about Windows PowerShell, including expert commentaries on the Microsoft Scripting Games, for which he has been a judge for the last four years. He has written two Windows PowerShell books: Windows PowerShell in Practice (Manning 2010) and Windows PowerShell and WMI (Manning 2012). He then collaborated with Don Jones and Jeff Hicks to write Windows PowerShell in Depth, which was published in 2013. Richard is currently writing an introductory book for Active Directory administrators that features Windows PowerShell.

Contact information: Richard Siddaway's Blog

Take it away Richard…

Thanks, Ed.

WMI has been with us for a long time, and it is one of those technologies that you either love or hate. (Some of us manage both at the same time, but that is another story.) Admins love WMI because it’s so powerful—if I can get a WMI connection to your machine, I can do just about anything to that machine. On the flip side, admins hate WMI because it can be very difficult to use, and finding information can be very difficult.

Windows PowerShell has had great WMI support, which was enhanced in Windows PowerShell 3.0 by the introduction of the CIM cmdlets and other WMI enhancements. The new functionality has caused some confusion because the WMI class methods, which we have come to rely on, seem to have disappeared.         

Before I show you what’s happened to your methods, I need to dive into a little WMI theory.

The starting point is that WMI is Microsoft’s implementation of the Common Information Model (CIM). CIM is part of the Web-Based Enterprise Management (WBEM) industry standards that are maintained by the Distributed Management Task Force (DMTF). WBEM is defined as “a set of management and Internet standard technologies developed to unify the management of distributed computing environments.”  WBEM standards are designed to be independent of the operating system and hardware. 

When you start Windows, the WMI repository is created. The repository consists of a number of things:

  • WMI providers (a DLL that provides access to WMI classes)
  • WMI namespaces
  • WMI class definitions
  • WMI instances

This is where some if the confusion arises. WMI classes can be taken to refer to the class definition (comparable to Active Directory schema definitions) and the class instances (compare to an object in Active Directory, such as a user).

When we only had the WMI cmdlets in Windows PowerShell 2.0, life was fairly simple in that you do things like this:

Get-WmiObject -Class Win32_Volume -Filter "Name = 'C:\\'" |

Get-Member -MemberType method 

And you would see the list of methods:

  • AddMountPoint
  • Chkdsk
  • Defrag
  • DefragAnalysis
  • Dismount
  • Format
  • Mount
  • Reset
  • SetPowerState

At this point, I need to remind you that the WMI is COM based, and the WMI cmdlets work over DCOM to local or remote machines.

You could access the methods by creating a Windows PowerShell object that represents the class, and call the method directly:

$disk = Get-WmiObject -Class Win32_Volume -Filter "Name = 'C:\\'"

$disk.DefragAnalysis()

The methods that you have seen so far are Instance methods. They only make sense and can only be used in the context of an instance. For example, you can’t perform DefragAnalysis against a non-existent volume!

Let’s skip over to Win32_Process for a minute:

Get-WmiObject -Class Win32_Process  | Get-Member -MemberType method

This produces the following list of methods:

  • AttachDebugger
  • GetOwner
  • GetOwnerSid
  • SetPriority
  • Terminate

Notice that there isn’t a Create method—these are all Instance methods. You have to have an instance of a process before you can terminate it.

When you are dealing with instances, you are dealing with the System.Management.ManagementObject .NET class. This is where some of the issues lie because you are working with a .NET wrapper for DCOM-based WMI.

Windows PowerShell is .NET based, and you can create just about any .NET object in Windows PowerShell. The Windows PowerShell team recognized that some .NET objects were of great interest to admins, and they provided shortcuts known as “type accelerators.” WMI has a number of type accelerators—in particular, the [wmiclass] type accelerator.

If you apply the [wmiclass] accelerator to the Win32_Process class, you get this:

$proc = [wmiclass]'\\.\root\cimv2:Win32_Process'

$proc | Get-Member -MemberType method

Name   MemberType

----   ----------

Create Method

We now have access to a method that we can use to create instances of the WMI class. The other important point is that we are dealing with a new .NET class: System.Management.ManagementClass. It’s a ManagementClass rather than a ManagementObject.

As a side note, the Create method is one of the intrinsic methods of a WMI class. It will always be there even if you can’t access it. Creating a new instance of the Win32_OperatingSysyem class could do interesting things to your machine!

In .NET terms, you can think of these as Static methods. You don’t need an instance of the class to utilize the methods. The WMI registry provider is a classic example of using WMI Static methods.

Get-WmiObject is a bit of a general work horse. You can use it to work with the instances of a WMI class, and you can use it to investigate WMI classes.

The Windows PowerShell 3.0 CIM cmdlets have separated these functions. Get-CimInstance is for working with instances of a WMI class only!

Get-CimInstance -Class Win32_Volume -Filter "Name = 'C:\\'" |

Get-Member -MemberType method

  • Clone
  • Dispose
  • Equals
  • GetCimSessionComputerName
  • GetCimSessionInstanceId
  • GetHashCode
  • GetObjectData
  • GetType
  • ToString

Hang on! This is totally different.  These aren’t the methods we want.

Remember that the WMI cmdlets work over DCOM to the local or remote machine. DCOM isn’t a firewall-friendly or Internet-friendly protocol. It also relies on an old programming methodology that is being replace by .NET.

The CIM cmdlets use DCOM to access the local machine if the –ComputerName parameter isn’t specified. As soon as you utilize the –ComputerName parameter to access the local or a remote machine, the CIM cmdlets switch to using WSMAN through the WinRM service. You can also use a CIM session with the CIM cmdlets. CIM sessions also work over WSMAN by default. (CIM sessions will be the subject of a future post.) 

WSMAN is the protocol that is used for Windows PowerShell remoting. Windows PowerShell remoting always returns an inert object—one that doesn’t have any methods. This is exactly the situation with the CIM cmdlets—they are designed to work over WSMAN, so they return inert objects.

The methods that you saw belong to the .NET class, which has changed from the WMI cmdlets. It is now Microsoft.Management.Infrastructure.CimInstance.

So far, it’s been established that you can’t access the Instance methods of a WMI class directly through Get-CimInstance. What you can do is pipe the results from your use of the Get-CimInstance cmdlet to Invoke-CimInstance to trigger the method, for example:

Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |

Invoke-CimMethod -MethodName Terminate

The Invoke-CimMethod cmdlet has an –Arguments parameter, so you can work with methods that need arguments.

Get-CimInstance enables you to access instances of a WMI class. How do you investigate WMI classes?

This is the function of the Get-CimClass cmdlet. It gives you access to the WMI class metadata (such as properties, methods, and parameters).

PS> Get-CimClass -ClassName Win32_Process | fl *

 

CimClassName        : Win32_Process

CimSuperClassName   : CIM_Process

CimSuperClass       : ROOT/cimv2:CIM_Process

CimClassProperties  : {Caption, Description, InstallDate, Name...}

CimClassQualifiers  : {Locale, UUID, CreateBy, DeleteBy...}

CimClassMethods     : {Create, Terminate, GetOwner, GetOwnerSid...}

CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties

Notice that the Create method is listed. Let’s drill down into the method definition:

PS> $class.CimClassMethods["Create"].Parameters

Name                       CimType Qualifiers

----                       ------- ----------

CommandLine                 String {ID, In, MappingStrings}

CurrentDirectory            String {ID, In, MappingStrings}

ProcessStartupInformation Instance {EmbeddedInstance, ID, In, MappingStrings}

ProcessId                   UInt32 {ID, MappingStrings, Out}

The fact that I get the parameter name and expected data type makes life so much easier. It’s worth upgrading to Windows PowerShell 3.0 for this alone.

Secondly, Get-CimClass gives you one way to access to the Static methods of a WMI class:

Get-CimClass -ClassName Win32_Process |

Invoke-CimMethod -MethodName Create -Arguments @{CommandLine='notepad.exe'}

The arguments are presented as a hash table with the parameter names as the keys. This removes the issue that arises with Invoke-WmiMethod, where the expected order of the parameters can change from that in the documentation.

One last piece of the puzzle remains: How can we tell if a particular method is a Static (or intrinsic) method as opposed to an Instance method? The information is buried in the qualifiers for the methods. Windows PowerShell MVP, Shay Levy, supplied the following script during the discussions that prompted this post:

$class = Get-CimClass -ClassName Win32_Process

$class.CimClassMethods | select Name, @{N='MethodType';

E={if ($_.Qualifiers['Static']){'Static'}else{'Instance'} }} 

Name           MethodType

----           ----------

Create         Static

Terminate      Instance

GetOwner       Instance

GetOwnerSid    Instance

SetPriority    Instance

AttachDebugger Instance         

You can derive the same information by using the WMI cmdlets:

$class = Get-WmiObject -List Win32_Process -Amended

$class.Methods | select Name, @{N='MethodType';

E={if ($_.Qualifiers['Static']){'Static'}else{'Instance'} }}

You need to be aware that using the –Amended parameter drills deep into the WMI repository, and it is an expensive operation in CPU cycles. It will take several seconds to return the data.

To return to the original question…

Dude, your methods are where they have always been. You just need to access them in a different way.

~Richard

Thanks, Richard! You can learn more about using WMI and the new CIM cmdlets with Windows PowerShell in Richard’s book, Windows PowerShell and WMI from Manning Publications. Join me tomorrow when Windows PowerShell MVP, Sean Kearney, will talk about Getting Funky with Windows PowerShell.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 


Viewing all articles
Browse latest Browse all 3333

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>