| < Day Day Up > |
|
More Information About WMI
If you are interested in a complete
Another great source of WMI information is Microsoft Developers Network (MSDN). Microsoft offers tutorials, whitepapers, sample code, and commands, and also describes all the WMI objects with their properties and
|
To browse the WMI schema, I recommend you do not use the Windows Server 2003 built-in tool (WBEMTest.exe), but rather install the WMI SDK (Software Developer's Kit) downloaded from Microsoft (make sure you get SDK version 1.5 minimum). The SDK comes with two great tools: Common Information Model (CIM) Studio and WMI Object Browser. CIM Studio allows browsing of any WMI schema metadata; all that is needed is the initial namespace and you get the following:
Classes with properties and methods
Schema information including inheritance
Data type and associations
Whereas CIM Studio is a metadata browser (only allows access to the schema), WMI Object Browser provides access to data. All object instances in a namespace can be accessed. It is possible to see values, update values, and execute methods. The interfaces are nearly identical between the two tools.
Most examples in this section will relate to Microsoft Cluster, but the examples can be easily modified to deal with almost any WMI providers.
Just as it takes two to tango, it takes three to make WMI useful! The three required elements are
OS support
: This is an available add-on for Windows NT 4.0 and built in to Windows 2000 and
Providers : Converts the data between native and WMI Application Programming Interface (API) and data structures. Most of the providers are new with Windows Server 2003.
Applications and/or UIs
: Applications are mostly left to a third-party; however, WMIC provides a simple
Obviously, this description is simplified, but it shows that the WMI providers are key elements that provide WMI with its richness. WMI does not limit providers to OS components; for example, Exchange 2000 ships with WMI providers. Over time, more products will ship with providers.
As previously mentioned, a WMI provider is a software layer that converts (thunk is the Microsoft
The definitive and complete description for each WMI provider is available on MSDN. However, for a simple introduction to what is available on your server, look at your server in the directory %WinDir%\system32\wbem for files with the extension Managed Object Format (.mof). Each of those files describes providers in a C-like format. You will be able to find:
The purpose for the provider, which is usually obvious from the file
The namespace location in the schema for the provider. For example, in the file DSProv.MOF:
Instance of __Namespace
{
Name = "LDAP";
};
#pragma namespace("\\.\root\directory\LDAP")
The object's properties and methods. For example, in the file TsCfgWmi.MOF:
class Win32_TerminalServiceSetting : CIM_Setting
{
[key,read] string ServerName;
[read] uint32 TerminalServerMode;
[read] uint32 LicensingType;
[read] string LicensingName;
[read] string LicensingDescription;
[read,write] uint32 ActiveDesktop;
[read,write] uint32 UserPermission;
[read] uint32 DeleteTempFolders;
[read] uint32 UseTempFolders;
[read] uint32 AllowTSConnections;
[read] uint32 SingleSession;
[read] string ProfilePath;
[read] string HomeDirectory;
[read] uint32 Help;
[read,write] string Logons;
[read] string DirectConnectLicenseServers;
[Implemented] uint32 AddDirectConnectLicenseServer([In] string LicenseServerName);
[Implemented] uint32 DeleteDirectConnectLicenseServer([In] string LicenseServerName);
[Implemented] uint32 ChangeMode([In] uint32 LicensingType);
[Implemented] uint32 SetAllowTSConnections([In] uint32 AllowTSConnections);
[Implemented] uint32 SetSingleSession([In] uint32 SingleSession);
[Implemented] uint32 SetProfilePath([In] string ProfilePath);
[Implemented] uint32 SetHomeDirectory([In] string HomeDirectory);
[Implemented] uint32 SetPolicyPropertyName([In] string PropertyName,[In] boolean Value);
};
A description of each property or method. For example, in DNSProv.MOF:
string ContainerName;
[Key, Propagated ("MicrosoftDNS_Domain.Name" ): ToSubClass,
Read: ToSubClass,
Description("This string represents the Fully Qualified Domain Name of "
"the Domain which contains this Resource Record. This property "
"may contain the strings, \"..Cache\" or \"..RootHints\", if the "
"DNS' internal cache or Root Hints (respectively) contain this "
"Resource Record." ): ToSubClass
]
note
The directory only contains files for components you have installed. For example, if your server is not configured as a DNS, the file DnsProv.MOF will probably not be there.
You can also learn more about the WMI providers on your server by browsing. You can browse the schema using the CIM Studio (the GUI from the WMI SDK mentioned previously). For example Figures 10.10 through 10.14 show what information is available from the cluster provider.
The default namespace is
\\Root\CIMv2
. When accessing objects, the path only needs to be specified if the objects are not stored in the default
WMI does not restrict the choice of programming language. Most developers will use a highly optimized language like C or C++. However, when doing simple management, it is possible to use WMI with minimum development effort or expertise using Windows Scripting Host (WSH). WMI can be scripted from any scripting language, but in this chapter Visual Basic Script (VBScript) is used to provide coding examples.
The VBS examples presented here are simple and are best executed using the CSCRIPT processor. Windows offers the choice of console-based scripting or windows-based scripting. However, only console-based scripting allows simple input and output interaction (some of the examples use the WScript.StdIn.Readline method to capture user input). To execute an example script, copy the script from this document using a simple editor like Notepad and save it using a unique file name like FOO.VBS. Then, use the console command:
C:\> cscript foo.vbs
The biggest
To get all instances from a class, use
GetObject(<Schema_Path>).InstancesOf(<class_name>)
To select a subset of objects in a class based on a criterion, use WMI Query Language (WQL which will look very familiar to you if you have ever worked with SQL):
GetObject( <Scema_Path> ).ExecQuery( <WQL> )
To get notification of an asynchronous event, use
ToGetObject( <Schema_Path> ).ExecNotificationQuery( <WQL> )
Beware that WMI returns object sets, even in the case of a set with a single object (such as a cluster, because a node can only belong to a single cluster at a time). For nonreal-time objects, loop through the object using the VBS syntax:
FOR EACH object IN objectset NEXT
The object properties defined in the class are accessed using the
ObjectName.PropertyName
syntax. For example,
InterfaceType
and
Size
are properties of the
DiskDrive
class and can be
DIM oResourceSet, oResource
SET oResourceSet = GetObject( "winmgmts://./root/CIMv2" ). _
InstancesOf( "Win32_DiskDrive" )
FOR EACH oResource IN oResourceSet
WScript.Echo( "Disk " & oResource.DeviceID & " has " & _
oResource.InterfaceType & " interface " & _
oResource.Size & " bytes" )
NEXT
SET oResourceSet = NOTHING
SET oResource = NOTHING
Methods are used to perform operations on objects. For example, renaming a printer requires more than changing the Name property. A method called RenamePrinter changes the name, updates the Registry, and does anything else that needs to be done. Another example involves pausing printers; the following VBS code would prompt for every printer that is running on a server and allow the user to pause it:
DIM oPrinterSet, oPrinter
CONST PAUSED=1
CONST RUNNING=0
SET oPrinterSet = GetObject( "winmgmts://./root/CIMv2" )._
InstancesOf("Win32_Printer")
FOR EACH oPrinter IN oPrinterSet
IF oPrinter.PrinterState = RUNNING THEN
Wscript.Echo( "Pause " & oPrinter.Name & "?" )
strInput = WScript.StdIn.ReadLine
strInput = UCASE( LEFT( strInput , 1 ) )
IF strInput = "Y" THEN
CALL oPrinter.Pause( )
END IF
ELSEIF oPrinter.PrinterState = PAUSED THEN
WScript.Echo( oPrinter.Name & " is paused." )
END IF
NEXTSET oPrinterSet = NOTHING
SET oPrinter = NOTHING
In general, a method
An association class
For example, one instance of MSCluster_ResourceGroupToResource has the following properties:
ResourceGroupTo.GroupComponent [ra]
MSCluster_ResourceGroup.Name="Cluster Group"
ResourceGroupTo.PartComponent [ra]
MSCluster_Resource.Name="Cluster IP Address"
The WQL is not valid because it includes the object name in the association. Turning these into valid WQL requires adding Select From at the front and replacing the period with Where and would produce:
Select * From MSCluster_ResourceGroup Where Name="Cluster Group" Select * From MSCluster_Resource Where Name="Cluster IP Address"
This can then be used as the argument of a WMI query:
GetObject( "winmgmts://./root/MSCluster" ).ExecQuery( <WQL> )
Association classes by
ASSOCIATORS OF {MSCluster_ResourceGroup.Name='Cluster Group'}
WHERE AssocClass=MSCluster_ResourceGroupToResource"
Using this WMI feature, it becomes trivial to use association classes. For example, the following code allows the user to specify a cluster group and will return all the
REM
REM Given a resource group name, find all the resources and
REM their types in that group using associators
REM
OPTION EXPLICIT
ON ERROR RESUME NEXT
DIM refWMIServices, oResourceSet, oResource, oResourceTypeSet
DIM oResourceType, strQuery, strInput, nCount
WSCript.Echo ("Enter name of the resource group to look for:" )
strInput = WScript.StdIn.ReadLine
SET refWMIServices = GetObject( "winmgmts://./root/MSCluster" )
strQuery = "ASSOCIATORS OF {MSCluster_ResourceGroup='" & _
strInput & "'} WHERE AssocClass=" & _
"MSCluster_ResourceGroupToResource"
SET oResourceSet = refWMIServices.ExecQuery( strQuery )
nCount = oResourceSet.Count
IF Err.Number <> 0 THEN
WScript.Echo ("Group " & strInput & " was not found!" )
WsCript.Quit
END IF
WScript.Echo ( "Got " & nCount & " resources in " & _
strInput & ":" )
FOR EACH oResource IN oResourceSet
WITH oResource
strQuery = "ASSOCIATORS OF {MSCluster_Resource='" & _
.Name & "'} WHERE AssocClass=" & _
"MSCluster_ResourceTypeToResource"
SET oResourceTypeSet = refWMIServices.ExecQuery( _
strQuery )
FOR EACH oResourceType IN oResourceTypeSet
WScript.Echo ( "Resource Name -> " & .Name & _
" of type -> " & oResourceType.Name )
NEXT
END WITH
NEXT
SET oResourceSet = NOTHING
SET oResource = NOTHING
SET oResourceTypeSet = NOTHING
SET oResourceType = NOTHING
Two association classes are used in this example:
MSCluster_ResourceGroupToResource
MSCluster_ResourceTypeToResource
Yet, no instances of those association classes are manipulated by the script! Also, the fact that the name field is the primary key for MSCluster_ResourceGroup and MSCluster_Resource shortens the syntax by omitting the .Name in the WQL string.
When accessing an object with the
GetObject
method, the system actually returns an in-memory private copy of the object. This
The object must be
You must update the local copy of the object by writing to Object.Property .
You must propagate the update to the system object using the SWbemNamedValueSet.Put_ method.
For example, this simple code will disable an account by updating the Disabled property (Here we pick on "Test User"):
DIM oUserSet, oUser, oNamedValueSet
CONST wbemChangeFlagUpdateOnly = 1
SET oNamedValueSet = CreateObject( _
"WbemScripting.SWbemNamedValueSet" )
CALL oNamedValueSet.Add ( "__PUT_EXTENSIONS", TRUE )
CALL oNamedValueSet.Add ( "__PUT_EXT_CLIENT_REQUEST", TRUE )
strQuery = "Select * From Win32_UserAccount Where Name=" & _
"""Test User"""
SET oUserSet = GetObject( "winmgmts://./root/CIMv2" ). _
ExecQuery( strQuery )
FOR EACH oUser IN oUserSet
EXIT FOR
NEXT
oUser.Disabled = "True"
arProperties = ARRAY( "oUser.Disabled" )
CALL oNamedValueSet.Add ( "__PUT_EXT_PROPERTIES", arProper-ties )
CALL oUser.Put_( wbemChangeFlagUpdateOnly, oNamedValueSet )
SET oUser = NOTHING
SET oUserSet = NOTHING
SET oNamedValueSet = NOTHING
note
The FOR EACH “ EXIT FOR “ NEXT construct in the previous code sample might look unusual at first; however, it is a simple technique to obtain the only object from an object set that we expect to contain only one object. For a more robust program, it would be advisable to check that oUserSet.Count=1 and take an error action if not. The Count property of an object set is an inherited property that always returns the number of items in the set.
Events are different from the previous objects in that they are not permanent, but rather happen in an asynchronous fashion in real time. After an event has
DIM oEvents, oItem
SET oEvents = GetObject( "winmgmts://./root/MSCluster" ). _
ExecNotificationQuery( "Select * from MSCluster_EventResourceStateChange" )
DO
SET oItem = oEvents.NextEvent
WITH oItem
WScript.Echo( DATE & " " & TIME & _
" EventNewState=" &.EventNewState & _
" EventObjectName=" &.EventObjectName & _
" EventObjectPath=" &.EventObjectPath & _
" EventObjectType=" &.EventObjectType & _
" EventTypeMajor=" & .EventTypeMajor & _
" EventTypeMinor=" &.EventTypeMinor )
END WITH
LOOP
SET oEvents = NOTHING
SET oItem = NOTHING
note
This simple code works, but good programming technique requires a user-triggered method to exit the loop. In this example, the code will never reach the cleanup section. It is assumed the user will terminate this using Ctl+C.
The goal of WMI is to standardize Windows management. However, until now, Microsoft has
WMIC is an incredibly powerful tool that provides a common interface and syntax to manage almost everything on a system. Because WMIC can manage anything that offers a WMI provider, Administrators and end users finally have access to the stated benefits of WMI.
The first time WMIC is invoked, the system
C:\>wmic Please wait while WMIC is being installed.
This only occurs the first time and takes less than 30 seconds.
WMIC has two separate sets of help:
The WMIC command uses /? for help and /?:FULL for advanced help. Everything in WMIC is context sensitive, which means that the help information displayed depends on what precedes the /? . The main problem with context-sensitive help is similar to a Catch-22; if I don't know where it is, I can't get there to ask for help!
The other set of help comes from the common "Help and Support." I recommend that everyone read though the WMIC help topics.
WMIC can generate output in any format desired. The default formats available are text, CSV, HTML, and XML. However, it is possible to define new formats.
WMIC commands are made of multiple context sensitive
In creating WMI queries, the WMIC options shown here are important in formatting the query to accomplish what you want. Following is a list of definitions of these options:
/NameSpace qualifier is only required for objects not in the default namespace.
You can also use the /Output:FileSpecification global switch.
PATH <object> specifies the object class you want to work with.
The WQL clause is optional, but allows selecting a particular object set. By default, all objects of the
The most useful verbs are GET, SET , and CALL. GET is used to get a property list. SET is used to modify a property. CALL is used to invoke a method.
The most useful final qualifiers are
/VALUE, /FORMAT:
Navigating the WMI schema with WMIC initially might appear like navigating a labyrinth. Using the /? command to get help greatly eases the feeling of navigating blind. The command WMIC /? will show you the syntax elements and also all the aliases defined.
The first step in navigating using WMIC is to discover aliases. An
alias
is nothing more that a shortcut. Microsoft includes aliases for the most useful classes. For example, the
WMIC /?
command will show you that there is an OS class. So to access the OS class, all you have do is type
WMIC OS
. However, the output will be very disappointing. By default, WMIC outputs text in table format. In this case, the table is very wide and only contains one row of information. To change the output in to a more useable column, you would type
WMIC OS GET /VALUE
. This produces the same output, but instead of being truncated to the right, it just
If you are interested in finding out what an alias actually points to, you can use the command WMIC ALIAS <Alias> GET /VALUE . Using this command will show that the OS alias actually points to Win32_OperatingSystem . So the following two commands are equivalent:
WMIC OS GET /VALUE WMIC PATH Win32_OperatingSystem GET /VALUE
Follow the same technique to browse all the available aliases. Some aliases might fall short on information; for example, if your test machine only has IDE
After you have found a class to investigate you can easily obtain more information about the class. For example, to find out the properties of the OS class, type WMIC OS GET /? . This will list all the properties available in the class. Similarly, the command WMIC OS CALL /? lists all the methods available.
note
Most properties and methods have descriptive names. But what if the descriptive name still does not
The previous sections introduced you to the WMIC commands. However, all the examples so far have been simple and resulted in immediate display of text results in a
WMIC formats results using common style sheets (files with .XSL extensions). To use the style sheet, simply add the /FORMAT:Style-sheet to a WMIC command. The standard style sheets provided are
CSV : Allows you to output the results to a file using comma-separated fields. This is great for sending data to a simple database or Excel.
HFORM : HTML with the data in list format. This format is great when viewing a lot of properties from a single object.
HTABLE : HTML with the data in table format. This format is best for viewing a few properties from a lot of instances. Optionally, the table can be sorted by using the syntax /FORMAT:HTABLE:"sortby=field_name"
MOF : Microsoft Operations Framework source file used to describe the WMI namespace.
RAWXML : XML data that can be easily imported into any XML-aware applications such as SQL.
XML : Generates HTML of the XML data.
The default style sheets can be found in the same %WinDir%\System32\WBEM directory as the MOF files. Also, you can create your own style sheet and translation; see TechNet at http://www.microsoft.com/technet/prodtechnol/windowsserver2003/proddocs/entserver/wmic_creating_format.asp.
Now that you have learned to use WMIC to extract system information and either display it or send it to an application, wouldn't it be nice if you could make it refresh the information at fixed intervals? That is exactly what the /EVERY qualifier does. You specify a repeat interval in seconds, and the command repeats over and over at fixed intervals.
Using a combination of
/OUTPUT
,
/FORMAT
, and
/EVERY
, it is now possible to use WMIC to create Web pages that are automatically updated and
You must understand some of the limitations of WMI and WMIC to prevent frustration:
WMIC does not allow access to asynchronous WMI event classes. In order to access events, you must perform WMI calls either from a high-level language (like C++) or from a scripting language. However, you can access events that have been logged to the Windows Event log using the Event Log provider.
WMIC does not allow access to linked private properties. For example, cluster resources have common properties (properties that all cluster resources have, such as PendingTimeout ) and they have private properties (such as IP addresses that only make sense for a resource of type IP address). Only common properties can be manipulated with WMIC.
WMI
The WMIC syntax checker is extremely picky, and you must be very careful. Make sure you preserve the order of the qualifiers and parameters.
Because the providers are an additional layer of software that adds overhead, WMI usually performs
So far, we have dealt in generalities. However, some WMI classes are especially useful for managing a server. The list is not
The class
Win32_NTLogEvent
provides access to the Windows NT event logs. It provides access to all entries
wmic ntevent where "logfile='Application' and eventcode=7026" get sourcename,message /value
produces the list of all system event 7026 (service failed to load).
The class
Win32_QuickFixEngineering
provides easy access to all hotfixes applied to a system. WMIC has a QFE alias, so the command
WMIC QFE GET HOTFIXID
will list ID of all hotfixes applied to a system. WMIC QFE will list all information (including IDs) known about the
The class Win32_BIOS provides easy access to your server's BIOS, especially the version and build date. WMIC has a BIOS alias, so the simple command WMIC BIOS GET /VALUE will show you most of what you will ever want to know without having to shut down and look at the BIOS using <F9 or F10>.
The class Win32_TerminalService offers access to remote Terminal Services. When managing servers, it is safer to leave administrative mode terminal services disabled until needed. This WMI class provides a simple interface to enable or disable remote Terminal Services. The following command
wmic /node:<IP or network name> /user:<Domain\User> path Win32_TerminalServiceSetting where AllowTsConnections=0 call SetAllowTsConnections 1
enables terminal services on a remote machine. If the password for the username specified does not match the local password, WMIC will prompt for the password. After you are finished performing your remote session, you can either disable remote connections from the computer property box or use the following command remotely:
wmic /node:<IP or network name> /user:<Domain\User> path Win32_TerminalServiceSetting where AllowTsConnections=1 call SetAllowTsConnections 0
| < Day Day Up > |