Showing posts sorted by relevance for query wmi. Sort by date Show all posts
Showing posts sorted by relevance for query wmi. Sort by date Show all posts

Monday, February 04, 2008

PowerShell's [WMI] Type Accelerator

In a recent blog post, I introduced PowerShell's WMI related type accelerators. In this post, I'll look at the [WMI] accelerator in more detail. As I explained earlier, the [WMI] type accelerator helps you to get directly to a particular WMI object. You provide a string containing the path to a particular WMI object and the [WMI]  adapter returns the WMI object (or not if it does not exist). This approach is a little easier than using Get-WMIObject in those cases when you actually know the details of which occurrence you want.

To illustrate this TA, let's look at a WMI Class, Win32_Share. We can find all the shares on a system like this:

PSH [D:\foo]: gwmi win32_share | ft -auto

Name   Path       Description
----   ----       -----------
E$     E:\        Default share
IPC$              Remote IPC
D$     D:\        Default share
ADMIN$ C:\WINDOWS Remote Admin
foo    d:\foo
C$     C:\        Default share

This is fine if you want to just see the shares.  But if you want to access a particular share's methods or properties you need to do a bit more  work. One simple way you can  get access to the Admin$ share is like this:

PSH [D:\foo]: $admin = gwmi win32_share | where {$_.name -eq "Admin$"}

This approach works, but it's a bit ugly and can take some time if there are a lot of shares on a system. And here's where the [WMI] TA works well as follows:

$admin2 = [wmi]"\\dc1\root\cimv2:win32_share.name='admin$'"

This is much easier to write, assuming you know how to construct the path string. A simple way to determine how to construct the path for this TA is to look at the __Path property on the actual object:

PSH [D:\foo]: $admin = gwmi win32_share | where {$_.name -eq "Admin$"}
PSH [D:\foo]: $admin.__Path
\\dc1\root\cimv2:Win32_Share.Name="ADMIN$"

To convert this path for use with [WMI], you need first to replace the double quotes to single quotes, then enclose the resulting string in double quotes prepended with [WMI].  One nice feature of this approach is that the returned object is an object, not a collection/array, which makes it easier to use.

When I was creating this blog post, I wondered if it was possible to create a WMI path using other properties. However this does not appear to work:

PSH [D:\foo]: $admin3 = [wmi]"\root\cimv2:win32_share.description='Remote Admin'"
Cannot convert value "\root\cimv2:win32_share.description='Remote Admin'" to type "System.Management.ManagementObject".
Error: "Invalid object path "
At line:1 char:11
+ $admin3 = [wmi] <<<< "\root\cimv2:win32_share.description='Remote Admin'"
PSH [D:\foo]: $admin3 = [wmi]"\root\cimv2:win32_share.path='c:\windows'"
Cannot convert value "\root\cimv2:win32_share.path='c:\windows'" to type "System.Management.ManagementObject". Error: "
Invalid object path "
At line:1 char:11
+ $admin3 = [wmi] <<<< "\root\cimv2:win32_share.path='c:\windows'"

There are two different formats you can se for the WMI path - with and without a machine name as follows:

$admin4 = [wmi]"\\dc1\root\cimv2:win32_share.name='admin$'"
$admin5 = [wmi]"root\cimv2:win32_share.name='admin$'"

The first format includes a machine name (\\dc1) while the second doesn't. The second format only works on the local machine whereas the first  can work across a network. There's only one small issue (feature?) of the first format which is that you can not provide credentials. Thus if you are logged onto your local machine with your normal userid/password, that set of credentials is used to access WMI. If those credentials do not allow you to access the remote server, then there's no way to provide credentials that would work.

I hope this is a clear explanation - let me know if  you'd like more details.

Tuesday, November 01, 2011

Introduction to WMI and PowerShell – A NEW Pluralsight Course

I am quite pleased to be able to announce I’ve finished my first video class for Pluralsight, Introduction to WMI and PowerShell. It’s now available for viewing for Pluralsight subscribers.  I’ve been watching it a bit this morning and it’s not bad, if I do say so myself. Smile

The course is a total of 2:29, and is broken down into 5 modules as follows:

  • Introduction to WMI and PowerShell (21:28) – Describes WMI in Windows and discusses some of the key WMI exploration tools. The module then looks at PowerShell support for WMI in PowerShell V3, and describes the WMI cmdlets. The module finishes with some of the gotchas you need to be aware of when using WMI with PowerShell.
  • Using PowerShell and WMI  (34:37) This module looks at accessing WMI data, including instances, instance properties and methods, WMI classes, and static class methods. We cover the use of the key WMI cmdlets and explain the use of Type Accelerators.
  • Practical PowerShell (24:42)  - This module looks at the range of data you can use in WMI. We show key namespaces and key classes you might leverage. The module also looks at some of the security settings you might make use of when using WMI in a Enterprise environment.
  • Using WMI Query Language (29:36) – Describes the WMI Query Language and how to use it with the PowerShell WMI cmdlets.
  • WMI Eventing (39:16) - This final module looks at accessing WMI events. It shows how to create both temporary and permanent event subscribers for intrinsic, extrinsic, and timer events. It also explains all those terms and shows how to leverage WMI’s eventing subsystem.

So if you are currently a Pluralsight subscriber, why not consider it? If nothing else, take the free trial – 10 days access to the entire library, including this course.

And also: a big thank you to Alexandar Nikolic (@alexandair on Twitter) for his proof reading of the course – much appreciated!!

Saturday, December 06, 2008

Discovering WMI using Windows PowerShell

Around 2 1/2 years ago, I wrote a blog item entitled Discovering Networking with Monad and MSH where I looked at some aspects of WMI and how to discover more. Since then, I’ve published a few more articles on WMI.

The key thing for IT Pros to understand is that WMI is both a friend and other folks’ friend. What I meant by that is that WMI was built to be an interface. And for Microsoft, that means developer focused. WMI was the way for one application to surface management information and for other applications to leverage that information. This enables tools such as SCCM (aka SMS) to do such cool things.

But with PowerShell, the various classes of information are but a simple command away. The key is the GET-WmiObject cmdlet. This cmdlet enables you to retrieve any WMI class and access both its properties and methods and that means considerable power. PowerShell also provides WMI type accelerators, such as [WMI] that further simplify the use of WMI.

So how does an IT Pro get started. The first thing, I suppose is to understand how WMI is structured. To simplify, WMI is implemented on a host. On that host, there is a set of information that is organised with a hierarchical namespace which breaks up the information in a structured manner. In each Node of the WMI namespace, you’ll find a number of classes. Each class has a definition (what it should/can contain) and instances. Each instance of a class represents a real-world occurrence of that object. The class and hence the instance contains properties and methods. You can use the properties for reporting and can also update the values of these properties for any instance (and create and manipulate new instances). Instances (and the class) contain methods that you can call to get an instance to do something. The details of the namespaces, classes, properties and methods are described on MSDN.

With PowerShell, however the best place to start is with MOW’s most excellent WMI Explorer. This tool is incredibly cool. First, because it’s written all in PowerShell, but more importantly, because it’s the best browser I’ve seen. It’s a big PowerShell script – when you run it, you can open WMI on a system and browse the namespaces. In each namespace node you can look at the classes in that node. And for each class, you can simply see both the existing instances as well as the definition of that class. Here’s a screen shot of this tool running on one of my workstations:

image

As an IT Pro, you should download WMI Explorer and explore. I’ll be posting more on WMI and PowerShell coming up.

Technorati Tags: ,,

Wednesday, January 30, 2008

WMI, PowerShell and PowerShell's WMI Type Accelerators

I've been playing with PowerShell's WMI interface as part of some writing work I'm doing. As I see it, PowerShell lacks built-in cmdlets to do everything. However that really is not a problem since a lot of thing can be pretty easily achieved using a few lines of PowerShell! 

PowerShell introduces the concept of type accelerators. These look like normal .NET types (type name specified inside square brackets), but they are managed by PowerShell itself. Type accelerators are just shortcuts to existing underlying functionality.

There are three WMI related type accelerators in PowerShell V1. If you are using  WMI with PowerShell, you really should know these three:

  • [WMI] - this TA helps you to get directly to a particular WMI object. You provide a string containing a detailed path to a particular WMI object and the TA returns the object. This is a little easier than using Get-WMIObject in those cases when you actually know the details of which occurrence you want.
  • [WMICLASS] - this TA gets you to a class definition. This then enables you to access WMI Class static methods. The Get-WMIObject enables you to get to instances, but to create new instances you need access to the static methods of the class.
  • [WMISEARCHER] - this TA helps you in terms of querying. When creating a WMISEARCHER, you specify a WQL query (e.g. Select * FROM Win32_Process WHERE Handlecount > 1000). You can use the searcher to execute that query and return results. This is a little easer for some times of administration.

WMI Type Accelerators are not well defined or well documented either on MSDN or inside the product itself. I hope my attempts at providing this information are useful - let me know what I'm missing and I'll try to add it. Over the coming week or so, I'll be blogging about each type accelerator in more detail. The posts also contain some simple sample code that demonstrates these cool features.

Did I mention - PowerShell rocks!!!

Technorati tags: , ,

Friday, May 22, 2009

PowerShell and WMI Namespaces

Over on Tim Benninghoff blog – he has an interesting post:: PowerShell and WMI namespaces. With WMI, the classes and intances are organised under a hierarchal namespace starting at the appropriately named “root”.  Individual nodes can have children which can in turn have children and so on. To some degree, namespaces are just defined by a product team and there is little consistency across software products (such is life!). But where to start?

Despite what Tim says about using the GUI, MOW’s most excellent WMI Explorer script is one fantastic tool. Not only is it a really good browser, but as Tim notes, it’s written in PowerShell which is even more cool. I use this script in most of my training courses to add value!

His post then goes on to describe two methods of obtaining the namespaces within WMI. There are two small problems with his examples. In his first example he has a minor typo – this should read as follows:

gwmi -namespace "root" -class "__Namespace" | Select Name

In Tim’s post, he spelt the class with just a single underline (“_Namespace”) not two (“__Namespace”). WMI is sadly very picky!  Tim’s other method works fine and as he says produces the same output as his first (well once corrected!). On my system, this produces the following output:

PSH [C:\foo]: gwmi -namespace "root" -class "__Namespace" | Select Name

Name
----
subscription
DEFAULT
MicrosoftDfs
CIMV2
Cli
nap
MicrosoftIISv2
SECURITY
RSOP
MicrosoftDNS
WebAdministration
WMI
directory
Policy
virtualization
Hardware
ServiceModel
MSAPPS12
Microsoft
aspnet

The second point is that his two methods just produce a list of namespaces under the root. Since each node in the namespace can have children, his two methods do not list all the namespaces in which you can find classes. This, IMHO, is once case where the GUI is a better tool – visualising the hierarchy in a tree control is a whole lot easier than trying to do it from the command line. And you get the names spaces in alphabetical order (although you could do pipe the output above to Sort-Object easily enough). On my workstation I see a number of subsidiary namespaces below root as you can see here:

image

 

WMI Namespaces are a good thing to understand, since many of the classes you might want to access using Get-WMIObject (et al) rely on the –NameSpace paramater (and the appropriate namespace name!).

Technorati Tags: ,,,

Tuesday, December 30, 2008

PowerShell’s [WMICLASS] Type accelerator

In January of this year, I wrote a basic article on PowerShell’s WMI Type Accelerators. A type accelerator is, in effect,a shortcut to some underlying .NET component. PowerShell comes with three type accellerators for WMI:
  • [WMI] – a shortcut way of getting to a single instance of a class. I described this type accellerator in an article in February.
  • [WMICLASS] – a short cut to a WMI Class definition to enable access to the class’s static properties and methods. I describe this type accelerator below.
  • [WMISEARCHER] – a short cut to .NET’s ManagementObjectSearcher enabling you to search for objects easily. This type accellerator is an opportunity for a future article.
The [WMICLASS] type accelerator takes a string containing a relative or absolute path to an WMI class, and returns a a System.Management.ManagementClass object that represents the specified class (as opposed to an occurance of that class). For example let’s take a look at the Win32_Share WMI Class. First, look at what Get-WMIObject returns, then look at what the [WMICLASS] type accelerator returns:
 PS c:\foo:\> Get-WMIOBjecct Win32_share | get-memberm
  TypeName: System.Management.ManagementObject#root\cimv2\Win32_Share
Name                MemberType   Definition
----                ----------   ----------
Delete              Method       System.Management.ManagementBaseObject Delete()
GetAccessMask       Method       System.Management.ManagementBaseObject GetAccessMask()
SetShareInfo        Method       System.Management.ManagementBaseObject SetShareInfo(System.UInt32 MaximumAllowed, System.String Descr...
AccessMask          Property     System.UInt32 AccessMask {get;set;}
AllowMaximum        Property     System.Boolean AllowMaximum {get;set;}
Caption             Property     System.String Caption {get;set;}
Description         Property     System.String Description {get;set;}
InstallDate         Property     System.String InstallDate {get;set;}
MaximumAllowed      Property     System.UInt32 MaximumAllowed {get;set;}
Name                Property     System.String Name {get;set;}
Path                Property     System.String Path {get;set;}
Status              Property     System.String Status {get;set;}
Type                Property     System.UInt32 Type {get;set;}
__CLASS             Property     System.String __CLASS {get;set;}
__DERIVATION        Property     System.String[] __DERIVATION {get;set;}
__DYNASTY           Property     System.String __DYNASTY {get;set;}
__GENUS             Property     System.Int32 __GENUS {get;set;}
__NAMESPACE         Property     System.String __NAMESPACE {get;set;}
__PATH              Property     System.String __PATH {get;set;}
__PROPERTY_COUNT    Property     System.Int32 __PROPERTY_COUNT {get;set;}
__RELPATH           Property     System.String __RELPATH {get;set;}
__SERVER            Property     System.String __SERVER {get;set;}
__SUPERCLASS        Property     System.String __SUPERCLASS {get;set;}
PSStatus            PropertySet  PSStatus {Status, Type, Name}
ConvertFromDateTime ScriptMethod System.Object ConvertFromDateTime();
ConvertToDateTime   ScriptMethod System.Object ConvertToDateTime();

PS c:\foo:\> [WMICLASS]'Win32_share' | get-member
   TypeName: System.Management.ManagementClass#ROOT\cimv2\Win32_Share
Name                MemberType    Definition
----                ----------    ----------
Name                AliasProperty Name = __Class
Create              Method        System.Management.ManagementBaseObject Create(System.String Path, System.String Name, System.UInt32 ...
__CLASS             Property      System.String __CLASS {get;set;}
__DERIVATION        Property      System.String[] __DERIVATION {get;set;}
__DYNASTY           Property      System.String __DYNASTY {get;set;}
__GENUS             Property      System.Int32 __GENUS {get;set;}
__NAMESPACE         Property      System.String __NAMESPACE {get;set;}
__PATH              Property      System.String __PATH {get;set;}
__PROPERTY_COUNT    Property      System.Int32 __PROPERTY_COUNT {get;set;}
__RELPATH           Property      System.String __RELPATH {get;set;}
__SERVER            Property      System.String __SERVER {get;set;}
__SUPERCLASS        Property      System.String __SUPERCLASS {get;set;}
ConvertFromDateTime ScriptMethod  System.Object ConvertFromDateTime();
ConvertToDateTime   ScriptMethod  System.Object ConvertToDateTime();
In this example, you can see that Get-WMIObject returns System.Management.ManagementObject objects, while [WMICLASS} returns System.Management.ManagementClass objects – in other words, different object types with different members. I note that the MSDN library documentation does not really differentiate static and object members clearly – so you just have to know which is which when dealing with WMI classes.
The object occurrences returned from Get-WMIObject contain three methods: Delete, GetAccessMask and SetShareInfo. These three methods operate on a particular occurrence, i.e. Delete means “delete this occurrence”. However, the object returned from [WMICLASS} both contains none of those three dynamic methods, but does create a static method: Create, i.e. create a new share.
Why bother with [WMICLASS] you might ask. The answer is simple: to access the static methods and properties/fields that the class exposes. In the case of theWin32_Share class, the class has a static method (create) and three dynamic methods( delete, GetAccessMask and SetShareInfo). If you want to create a new share, then use [WMICLASS] to get access to the create method. You can get access to the Delete method by getting the appropriate method. This bit of code illustrates this:

.SYNOPSIS
    Demonstrates WMI and Win32_Share
.DESCRIPTION
    This script looks at objects retured from Get-WMIObject, and [WMICLASS] and demonstrates
    the use of a static method (create) and a dynamic or object method (delete).
.NOTES
    Author   : Thomas Lee - tfl@psp.co.uk
.LINK
    http://www.pshscripts.blogspot.com
.EXAMPLE
    Left as an exercise for the reader
#>

# Display shares at start
$start = get-wmiobject win32_share | where {$_.name -match "Foo"}
if ($start) {
  "{0} foo shares at start, as follows:" -f $start.count;
  $start}
else {"No foo shares"}

# Create a foo22 share
"";"Adding Foo22 share"
$class = [WMICLASS]'win32_share'
$ret = $class.create("c:\foo", "foo22", 0,$null,"Test Share Creation with WMI")
if ($ret.returnvalue -eq 0){
"Foo22 Share created OK"}
else {
"Share not created, error code: {0}" -f $ret.returnvalue
}

# Display results
"";"Foo shares now:"
get-wmiobject win32_share | where {$_.name -match "foo"}
""

# Delete the foo22 share
$del = Get-WmiObject win32_share | where {$_.name -eq "foo22"}
$ret = $del.delete()
if ($ret.returnvalue -eq 0){
"share deleted OK"}
else {
"Share not deleted, error code: {0}" -f $ret.returnvalue
}

# Display final results
"";"Foo at the end:"
$finish = get-wmiobject win32_share | where {$_.name -match "foo"}
if ($finish) {
  "{0} foo shares at the end, as folllows:" -f $start.count;
  $start}
else {"No foo shares at the end:"}
""
This sample, after the now obligatory Advanced Function help stuff, obtains and displays any shares on the local system that contain the string “foo”. Then, in line 24 the scripts gets the Win32_Share class, and in line 25 used the create static method to create a new share (Foo22). In line 39, the script deletes the newly added share, and finally prints out the remaining shares matching “foo”.
In summary, the [WMICLASS] gives you access to the static methods or members exposed by a WMI class.

Wednesday, January 14, 2009

Date and Time in PowerShell (and WMI)

In yesterday’s PowerShell script of the day entry,posted over on my PowerShell scripts blog, I re-implemented an MSDN sample (originally written in VBScript) that calculates up time. The script first used a WMI class (Win32_OperatingSystem) to determine when a computer started. Then the script gets the current time, and works out and displays the difference (i.e. the current uptime).

The .NET framework contains a class, System.DateTime, that provides a variety of time/date related features.The PowerShell Cmdlet Get-Date returns a System.DateTime object that contains the current date and time. You can use the methods and properties of the class to get aspects of that current date and time as you need. For example:

PSH [D:\foo]: $d=Get-Date
PSH [D:\foo]: $d.Date

14 January 2009 00:00:00

PSH [D:\foo]: $d.Year
2009
PSH [D:\foo]: $d.IsDaylightSavingTime()
False

You can, of course, pipe your DateTime object to Get-member to see the other properties and methods on this class (or refer to the MSDN documentation). There’s a lot of pretty rich date and time handling available.

The problem I had with yesterday’s script is that WMI uses a different format for date and time. The Win32_OperatingSystem WMI object has a property, LastBootUpTime which returns the date and time when the OS was last booted. However, WMI returns this as a string that is formatted rather differently to System.DateTime, as you can see here:

PSH [D:\foo]: $os=Get-WmiObject Win32_OperatingSystem
PSH [D:\foo]: $os.LastBootUpTime
20090112142457.454125+000

This demonstrates that .NET, and therefore PowerShell, uses a native date/time formats that are different. For many admins (and for most native level developers) this is not a big deal. But if you need to inter-operate, you have a small issue of converting between the two formats.

As it turns out, solving this issue is simple. The developers of .NET created a simple solution. First, there’s a .NET class,  System.Management.ManagementDateTimeConverter, which does date and time conversion. This class has a method, ToDateTime, which converts a WMI date string into a .NET DateTime object. I used this  method in the WMIDateStringToDate function in Get-Uptime.ps1.

You can either implement a function (i.e. WmiDateStringToDate) in your profile or cut/pasted it into any WMI script you write. Naturally, you could just use the .NET method natively. As follows:

PSH [D:\foo]: $os=get-wmiobject win32_operatingsystem
PSH [D:\foo]: $time = $os.lastbootuptime
PSH [D:\foo]: [System.Management.ManagementDateTimeconverter]::ToDateTime($time)

12 January 2009 14:24:58

PSH [D:\foo]: ([System.Management.ManagementDateTimeconverter]::ToDateTime($time)).hour
14

As with most things PowerShell, easy stuff is very easy while complex stuff is often just a method call away.

Friday, July 22, 2005

Discovering Networking with Monad and MSH

Monad presents administrators with great features and facilities, but there is a learning curve. One key aspect of learning any new feature or product is the aspect of "discoverability" - the ability to find things out simply. There are several ways to discover things, but the built-in reflection methods are at hand to help (although getting used to Monad and>.NET is a learning curvre!).

With Windows XP, there are over 900 WMI classes returned from the Get-WmiObject -List command, as shown:


[C:\]: $wmi=Get-WmiObject -list
[C:\]: $wmi.length
920
[C:\]: $wmi | format-list
(... a long list not shown!)

WMI class names are relativey self explanatory - so to find all the WMI classes that have 'net' or 'networking', you can do the following:

[C:\]: $netsettings = $wmi | where {$_.__PATH -match "net"}
[C:\]: $networksettings = $wmi | where {$_.__PATH -match "network"}

You can then use these to get the key network class names, as follows:

[C:\]: $netsettings.length
89
[C:\]: $networksettings.length
14
[C:\]: $networksettings | ft __Path

__Path
------
\\KAPOHO61\ROOT\cimv2:Win32_TSNetworkAdapterSettingError
\\KAPOHO61\ROOT\cimv2:Win32_NetworkClient
\\KAPOHO61\ROOT\cimv2:Win32_NetworkProtocol
\\KAPOHO61\ROOT\cimv2:CIM_NetworkAdapter
\\KAPOHO61\ROOT\cimv2:Win32_NetworkAdapter
\\KAPOHO61\ROOT\cimv2:Win32_NetworkConnection
\\KAPOHO61\ROOT\cimv2:Win32_PerfRawData_Tcpip_NetworkInterface
\\KAPOHO61\ROOT\cimv2:Win32_PerfFormattedData_Tcpip_NetworkInterfac
\\KAPOHO61\ROOT\cimv2:Win32_SystemNetworkConnections
\\KAPOHO61\ROOT\cimv2:Win32_TSNetworkAdapterSetting
\\KAPOHO61\ROOT\cimv2:Win32_TSNetworkAdapterListSetting
\\KAPOHO61\ROOT\cimv2:Win32_NetworkLoginProfile
\\KAPOHO61\ROOT\cimv2:Win32_NetworkAdapterConfiguration
\\KAPOHO61\ROOT\cimv2:Win32_NetworkAdapterSetting

Once you have these names, you can begin exploring:

[C:\]: $nw=Get-WMIObject Win32_NetworkAdapter
[C:\]: $nw.length
31
[C:\]: $nw | gm
(long display - deleted)

Thursday, September 22, 2011

Using PowerShell and WMI to Manage the Registry

For those of you who are very keen eyed, you may have noticed some posts on my PowerShell Scripts blog related to the WMI Registry Provider. I’ve been working on a PowerShell and WMI course which will be published by Plural Sight in October. As part of this, I have been playing with WMI and the Registry provider, which you can easily use via PowerShell.

Microsoft has implemented a nice registry provider withing WMI: the StdRegProv class in the ROOT\DEFAULT WMI class.  This class contains 20 static methods that enable you to perform any Registry action on a local or remote computer. You can access these in two ways, either using New-Object to create a new System.Management.ManagementClass object, specifying the path to the class to the constructor ("Root\default:StdRegProv"). Alternatively, you could use the [WmiClass] Type Accelerator, specifying [WmiClass]"Root\default:StdRegProv". Both return the class object, which contains a number of methods as shown here:

c:\> $x=new-object System.Management.ManagementClass "Root\default:StdRegProv"
c:\> $x.Methods | ft name

Name                                                 
----                                            
CreateKey                                                
DeleteKey                                                
EnumKey                                                  
EnumValues                                                
DeleteValue                                                
SetDWORDValue                                                
SetQWORDValue                                                
GetDWORDValue                                                
GetQWORDValue                                                  
SetStringValue                                                 
GetStringValue                                                 
SetMultiStringValue                                                
GetMultiStringValue                                                 
SetExpandedStringValue                                                
GetExpandedStringValue                                                 
SetBinaryValue                                                
GetBinaryValue                                                
CheckAccess                                                 
SetSecurityDescriptor           
GetSecurityDescriptor   

In effect you have four sets of methods:

  • Create/delete registry key (CreateKey, DeleteKey)
  • Enumerate a registry key or value entry (EnumKey, EnumValue)
  • Create, set or delete a value entry (Set<valuetype>Value, Get<valuetype>Value, DeleteValue)
  • Check security on a value/key (Check Access, SetAccessDescriptor, GetSDecurityDescriptor)

Each method is very easy to call, as you will have seen on my PshScripts blog. To manipulate the registry, you need to specfiy a registry Hive, a Registry Key, and where needed, a registry value. So to create a registry key, you could do this:

$HKEY_LOCAL_MACHINE = 2147483650
$Reg                = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Key                = "SOFTWARE\NewKey"
$Results            = $Reg.CreateKey($HKEY_LOCAL_MACHINE, $Key) 

In this case, you specify the  hive to create the key in by specifying a well known value, in case, 2147483650. The well known values are as follows:

HKEY_CLASSES_ROOT     2147483648
HKEY_CURRENT_USER     2147483649
HKEY_LOCAL_MACHINE    2147483650
HKEY_USERS            2147483651
HKEY_CURRENT_CONFIG   2147483653
HKEY_DYN_DATA         2147483654
With PowerShell, you first instantiate the class instance, which gets you an object on the local or remote machine. Then, you pass the static methods of htios class the values necessary. You always need to the specific well known numbers – in my example above, via a variable to the call the appropriate registry operation. The other paramaeters will depend on the specific call being made.
 
So to create a new MultiString regisgry value, below the key created earlier, you could do this:

$HKEY_LOCAL_MACHINE = 2147483650
$reg       = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Key       = "SOFTWARE\NewKey"
$ValueName = "Example MultiString Value"
$Values    = @("Thomas", "Susan", "Rebecca")
$Key       = "SOFTWARE\NewKey"
$reg.SetMultiStringValue($HKEY_LOCAL_MACHINE, $Key, $ValueName, $Values)

In this case, the code created a new MultiString value. There are no explicitly NEW methods on StdRegProv – you use a Set* method to either create a new value entry or change a value. With both getting and setting value entries, you use different methods depending on the specific value type you wish to manage (String, Multi—String, Binary, etc).  With removing a value, there’s only one method: DeleteValue.
 
One small thing to be careful of, DeleteKey, deletes the key specified and everything below it. So Deleting a key of “\” in most of the well known hives is probably not advisable.
 
All in all, it’s darn easy to use the StdRegProv class with PowerShell for all your registry manipulation needs.
Technorati Tags: ,,
 
 

Sunday, February 07, 2010

Solarwinds – Free WMI Monitor

I am slowly pulling together my upcoming PowerShell Master Class. One of the modules looks at WMI objects and I’ve been searching for as many cool tools etc as I can find. Thanks to a couple of tweets (Shay and Doug!), I found a pretty cool free tool from Solarwinds, called WMI Monitor. This is a free download that does a number of things, including:

  • monitors the performance on a Windows server
  • leverages pre-built and community generated application templates for monitoring virtually any application
  • enables you to modify or design your own application templates with the built-in WMI browser

This tool is free, but you do have to register. Also – it’s a 60mb download! But if you are doing WMI scripting with PowerShell, it might well be worth the download.

Technorati Tags: ,,

Tuesday, April 21, 2009

Fun and Games with WMI and PowerShell

As I continue to dive deeper into PowerShell WMI, I continue to be surprised by new things I discover. I’ve been playing today with the WMI Class WIN32_printer. Sometime ago, I posted a code sample over on MSDN using this class with Powershell (see the original sample here).

The original sample produced a test page on a specific printer – but I thought it would be interesting to see what happened if I ran the script against ALL the printers define on my workstation. And that got interesting.

On my system, I have two ‘real’ printers installed (a colour Inkjet and a colour  laser) and two additional printers: an XPS Document Writer “printer” and a SnagIt 9 “printer”. As expected, the real printers printed their test pages just fine. But the virtual printers did not fare so well. The SnagIt printer failed to print a test page. It generated two “Unable to open message queue” error messages (in a pop-up window), then failed with a message “Unable to send a message to SnagIt” (and another pop-up). But at least it failed gracefully although the Result code was 0. Attempting to print to the XPS document writer just hung.

This result shows that, at least with WMI (and probably ALL other classes), when you start writing scripts based on base objects (i.e. WMI, COM, .NET and home grown), you need to know what you are doing. And in writing production scripts, you need to be extra careful with testing, and coding around the problem issues.

This last point is illustrated in the updated script that I published to my scripts blog: http://pshscripts.blogspot.com/2009/04/get-printertestpageps1.html. Look at lines 63-65 – these avoid calling the PrintTestPage on those printers you know to not work. This is another interesting reference to the fact that production scripting is more about “error” handling (you might call it “reality handling” too"!) than anything else. And a lot of wide testing.

Technorati Tags: ,,

Tuesday, June 21, 2005

WMI Scripting with MSH

If MSH is to become the next best scripting thing, then its got to enable a number of different scenarios. One use of MSH is to do WMI scripting - using MSH get access to WMI objects, properties and methods.

I started by looking at the [truly amazing!] TechNet script centre, which has a large number of existing WMI scripts. As it turns out, it's surprisingly easy to write WMI scripts, once you master the differences between VBscript and Monad!

The first script I tackled is at: http://www.microsoft.com/technet/scriptcenter/scripts/desktop/logon/dmlgv b02.mspx

'-----------
strComputer = "atl-ws-o1"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colComputer = objWMIService.ExecQuery _ ("Select * from Win32_ComputerSystem")
For Each objComputer in colComputer
Wscript.Echo "Logged-on user: " & objComputer.UserName
Next
'------------

In MSH this is just 3 lines:

$strComputer = "kapoho61"
$colComputer = get-wmiObject win32_computersystem -comp $strComputer
foreach ($comp in $colcomputer){"Logged-on user: " + $comp.username}

8 lines into 3 - not bad!

My second attempt was to reproduce http://www.microsoft.com/technet/scriptcenter/scripts/desktop/logon/dmlgv b01.mspx

'-------------- strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_LogonSession")
For Each objItem in colItems
Wscript.Echo "Authentication Package: " & objItem.AuthenticationPackage
Wscript.Echo "Logon ID: " & objItem.LogonId
Wscript.Echo "Logon Type: " & objItem.LogonType
Wscript.Echo "Start Time: " & objItem.StartTime
Wscript.Echo
Next
'--------------

Becomes:

$strComputer = "kapoho61"
$colComputer = get-wmiObject win32_LogonSession -comp $strComputer
foreach ($comp in $colcomputer) {"Authentication Package: " + comp.AuthencationPackage
"Login ID: " + $comp.LogonId
"Login Type: " + =$comp.LogonType
"Start Time: " + $comp.StartTime}

11 lines into 6.

All in all - this WMI scripting stuff looks to be easy in MSH. What would be really cool now is for someone to create a msh-scriptomatic.hta (to mimic the scroptomatic.hta currently available). I just wish I was better at HTAs.

MSH Rocks!!

(submitted by email - apologies for layout!)

Friday, April 24, 2009

Windows Management Infrastructure Blog

The WMI team are now blogging in the Windows Management Infrastructure Blog. A most useful blog for those wanting to understand WMI (and BITS, and WINRM) especially those coming to this from a PowerShell point of view. One interesting post examines the WMI story, pre Windows 7 (with lots of great links to more background). Another post looks at what is coming with WMI in Windows 7 (i.e. with PowerShell V2).

This blog is well written! And any blog that can mix PowerShell, reindeers, Jedis, ands and grasshoppers can’t be all bad!

Technorati Tags: ,,

Thursday, August 06, 2009

Static vs Dynamic WMI Methods with PowerShell

In yesterday’s  PowerShell and .NET Framework – Similarities and Differences! article, I wrote about how there was stuff you have to know in order to use PowerShell efficiently. In a recent Hey, Scripting Guy! Blog article, The Scripting guys talk about the differences between a static method on a class and an instance-based method. They use the WMI Win32_Process class as an example. In this WMI class, there is an instance based method, Terminate, that lets you terminate a specific process. As the Scripting Guys point out, there’s no Create method. That’s because the  Create method is a static method which you invoke a slightly different way.

To create a process, you’d do the following:

PSH [C:\foo]: ([wmiclass]"Win32_Process").Create("NotePad")

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ProcessId        : 8828
ReturnValue      : 0

This is yet another one of those things you need to know about using WMI with PowerShell: how to access static vs. instance based methods.

Technorati Tags: ,,

Sunday, June 26, 2005

More on WMI Scripting With MSH

In my last blog post, I got quite excited about the ability to do WMI scripting from MSH. That post generated a lot of feedback - Mark Allen's post was, as ever on the money. No, I was not trying to say short is better because it's short. APL proved that readability was more important than pure brevity. But what impressed me about WMI scripting using MSH was that it is so easy and obvious when compared to VBScript. I can see that part of my message was lost when the mail to blog translation happened - the script examples looked a lot better in my mail than they did when first rendered on this site. I've tidied up the layout a bit on that post to make the intention clearer.

I also got mail from the MSH development team pointing out I could have made the scripts shorter still, They are, of course, right! The two scripts I posted were meant to show a straightforward comparision between WMI scripts on the Script Centre, and ones you could easily write with MSH. I was trying to show MSH scripts were shorter, simpler to understand and faster/easier to develop.

Of course if you want terseness, the following script prints out the logged on user, all in one one line (well one line when I typed it!):

foreach ($comp in Get-WmiObject Win32_ComputerSystem -comp "kapoho61") {"Logged-on user: $($comp.UserName)"}

Or to simplify every further, here's an even simpler "script":

$(get-WmiObject Win32_ComputerSystem -comp "kapoho61").UserName

So to answer Mark Allen - no, I'm not advocating shortness just for the sake of it. For any production script, you have to have readibilty (and comments) and adopt a simple to maintain style. But when it's a simple as the examples here and before, you can see how much easier MSH can make both scripting WMI and scripting in general. What continues to amaze me about MSH is that there are so many ways to achieve the same end - and just about all of them shorter, and simpler than VBScript.

Saturday, June 16, 2007

WMI Win32_Volume Class using PowerShell

I've been playing around this weekend with PowerShell and the Win32_Volume WMI class and have written some PowerShell scripts to exploit this class.

To get the volumes on a system is trivial:

$volumes = Get-WMIObject Win32_Volume

This returns an array of volume objects which you can iterate through and display. To display the whole collection, or to just see the first volume, you could do this:

$volumes
$volumes[0]

See here for a simple script that obtain the volumes on a system and then displays their information. Then look at this script to run a chkdsk on the system.

You can also use a method to determine how badly fragmented a volume is, and another to run a defrag pass on a volume. Look here for a script to display a defrag analysis of the C:\ and here to actually defrag the disk.

 

[Later Update]

The Win32_Volume WMI class is not available on all versions of Windows - I ran the scripts on a Longhorn B3 server.

 

Technorati tags: , ,

Wednesday, November 09, 2011

Performance with PowerShell

Over the weekend, at the most recent PowerShell PowerCamp, I got to discussing the performance of PowerShell. The point I was making was that PowerShell made doing some things very easy, even though they were not performant. Two examples are the early filtering  of WMI data using –Filter (vs using Where-Object after you retrieve all the data from a remote machine) and the two variants of ForEach.

In the case of WMI, where you early filter properties/occurrences on the target machine, PowerShell has less data to serialize and transmit across the network. Also, late filtering requires more local memory, and additional processing. Thus I’d expect early filtering to be faster. We are thus comparing two statements which might look something like this:

Get-WMIObject win32_share -computer  Cookham1 -filter "Description='remote admin'"

versus

Get-WMIObject win32_share -computer  Cookham1  | Where {$_.description -eq 'remote admin'}

In the first example, only one share is returned from Cookham1, whereas in the second example multiple shares are returned and are then filtered locally (aka late filtering). If I wrap both of these commands in a Measure-Command, and do the operation a number of times, the code and results look like this:

 

Psh[Cookham8:fmt:\]>"Early Filter:"
" {0} ms"  -f  ((Measure-command {1..100 | foreach {
Get-WMIObject win32_share -computer  Cookham1 -filter "Description='remote admin'"}}).totalmilliseconds).tostring("f")

"Late filter:"
" {0} ms"  -f  ((Measure-command {1..100 | foreach {
Get-WMIObject win32_share -computer  Cookham1  | Where {$_.description -eq 'remote admin'}}}).totalmilliseconds).tostring("f")
Early Filter:
1948.91 ms
Late filter:
2715.44 ms

So the difference between late filter and early filter is around 28%, although if I run this test a few times, the numbers do vary a bit, but almost always early filtering is in the region of 20% faster.

But a much bigger difference was observed by Anita Boorboom, a Dutch SharePoint guru, in the second case, i.e. using For-Each-object (vs using ForEach in a pipeline).

When you use the foreach operator in a pipeline, PowerShell is able to optimise the creation of objects at one stage of a pipeline and their consumption in the next. Using Foreach-Object, you need to first persist all the objects you wish to iterate across, then perform the iteration. The latter clearly requires a bit more processing and it is likely to require more memory (which can be a bad thing if the collection of objects is large! I knew this, but Anita’s results were a little more than I was expecting, so I duplicated her scripts, well nearly, and found here results were indeed correct, like this:

$items = 1..10000
Write-Host "ForEach-Object: "
" {0} ms"  -f ((Measure-Command { $items | ForEach-Object { "Item: $_" } }).totalmilliseconds).tostring("f") 
Write-Host "Foreach: "
" {0} ms" -f ((Measure-Command {Foreach ($item in $items) { "Item: $item" }}).totalmilliseconds).tostring("f")
ForEach-Object:
  629.73 ms
Foreach:
31.84 ms

Thus the pipelined foreach is nearly 20 times faster for this experiment. I ran this code several times, and the multipler was consistently in the 20-30 times as fast range. That floored me. The For-Each Object does require PowerShell to instantiate every object in memory, then to iterate over it, vs iterating as it instantiates. But I did not expect a 20-30 fold difference in performance!

So it’s obvious that some language constructs will be a little more efficient, You also need to consider the time it takes to write the code, and how often it will be run.  In the first case above, I managed to save just over 750ms by using early WMI filtering. But it probably took me more than that just to write the code for early binding. And for a lot of admins that don’t know WMI very well, filtering using Where-Object is familiar and uses PowerShell Syntac (the –filter clause on Get-WMIObject used WQL which is different). In the second case, the difference was staggering. Of course, when the processing you want to apply to the collection members is non-trivial (i.e. more than a couple of lines of code), you often find the improvement in readability of the resulting script block to be worth considering. By using task oriented variable names, the resulting code is easier to read then when you use $_. And for some production orient5ed scripts, that improvement in readability may be worthwhile.

In summary, there always a lot of different ways to achieve the same result in PowerShell. I advocate using what is easiest for you to remember. At the same time, PowerShell can provide some big performance differences between the approaches – and it pays to know more!

Technorati Tags: ,

Monday, December 29, 2008

Type Accelerators for PowerShell CTP3

Type Accelerators are a PowerShell feature that simplifies access to underlying WMI or .NET objects. Earlier this year I wrote two blog articles, the first about the WMI type accelerators and the second specifically about the [WMI] type accelerators. At some point, I intend to write about the other two ([WMICLASS] and [WMISEARCHER]) WMI related type accelerators.
In a most interesting Christmas Day post, Osin posted a detailed look at Type Accelerators within PowerShell CTP3. By using Reflector to look at the actual PowerShell code, you can see how PowerShell implements Type Accelerators, through using the TypeAccellerator class. Neat! But neater still, Osin shows how to make use of this technique to both list out the existing Type Accelerators as well as how to add more.
Here’s a simple function definition that returns the existing type accelerators:

function Get-Typeaccelerator
{  #  reference the accelerators
     $acceleratorsType = [type]::gettype("System.Management.Automation.TypeAccelerators")  
  #  return all built-in accelerators (property)     return $acceleratorstype::get.GetEnumerator()|
     select @{Name="Name"; expression={$_.key}},
     @{name="Type"; expression={$_.value}} | sort name
}


Saturday, March 02, 2013

WMI Explorer–Where’s It Gone–A Temporary Solution

As a trainer, teaching PowerShell, I use WMI Explorer heavily. For those who may be unfamiliar, this is a PowerShell script that displays information about WMI on a system. Written by MOW, a PowerShell MVP, it is for me the best tool I can find for displaying WMI data to the class.
The bad news is that for some reason, it’s old home is not resolving – so all the search engine listings point to a host that for some reason is not there.

In the meantime, I’ve put a copy here: https://docs.google.com/document/d/1kuyoyFSc-wNRZBZjWI3aNjIMdw48hYS9Av4S_iNMBwI/edit?usp=sharing

Monday, December 08, 2008

PowerShell WMI Based Audit Script

I’ve been writing about WMI and PowerShell of late – and notices this cool PowerShell Audit Script on Alan Renouf’s Virtu-Al’s blog. It’s not a particularly new post, but the result if pretty awesome. It produces a nice rich HTML file as output that looks a bit like this:

image

A great demonstration of what you can get from WMI plus what you can do with HTML in PowerShell

Technorati tags: ,