Common Information Model (“CIM”)

CIM may be used by other standards: Wikipedia's article on Common Information Model (computing): section titled “Scheme and specifications” notes, “CIM is the basis for most of the other DMTF standards (e.g. WBEM or SMASH). It is also the basis for the SMI-S standard for storage management.”

“Web-Based” Enterprise Management (“WBEM”)

First, note that the name may be a bit misleading: Wikipedia's artcile on Web-Based Enterprise Management notes, “Although the name refers to WBEM as being "Web-Based", it is not necessarily tied in any way to a particular user interface”. Also, there is no particular need to restrict usage of this to organizations that are large enough to typically use “enterprise”-level options.

Wikipedia's article on Common Information Model (computing): Overview section notes (about CIM): “A related standard is Web-Based Enterprise Management (WBEM, also defined by DMTF) which defines a particular implementation of CIM, including protocols for discovering and accessing such CIM implementations.”

[#mswinwmi]: Windows Management Instrumentation (“WMI”) for Microsoft Windows

WMI is an approach to being able to interact with a certain “objects”. (The term “objects”, as used here, refers to “object-oriented” concepts as found in object-oriented programming (“OOP”). Some software, quite notably Microsoft Windows, may provide such “objects”. Frequently, these objects provide an ability to check on various statuses, so this can be a quite effective way to get information. Furthermore, at least some WMI interfaces are very automatable.)

Support for WMI/WBEM
Support for WMI/WBEM in Microsoft Windows
Windows XP and newer (including Windows Server 2003)

Comes with WMI installed, and comes with WMIC command line utility.

Windows 2000
Currently believed to be the same story as Windows Millenium Edition (“Windows ME”)
Windows Millenium Edition (“Windows ME”)

Included. MS KB Q322363 notes, “By default, Windows Management Instrumentation is installed on computers running Windows Me.” The operating system does not provide any simple method “for the installation or the removal of Windows Management Instrumentation. WBEMTest and Wmicli.exe work correctly on this version of the Windows operating system.” Options for disabling WMI are discussed by MDGx page on WBEM (WINMGMT) in Windows ME.

Windows 98 Second Edition

Win98SE comes with WBEM as an optional component that can be installed either during the operating system's installation, or after the operating system installed. Installing this can be done easily if the operating system CD's installation files are readily available, using the Control Panel's Add/Remove Programs, “Windows Setup” tab. In either scenario (during the operating system's installation, or after the operating system is installed), choose the category called “Internet Tools” and then choose “Web-Based Enterprise Mgmt”.

However, C:Amie article on WMI in Win95/98(SE) recommends removing this version of WBEM if it has been installed.

Windows NT 4.0

MS KB Q219378 notes that an installer for WBEM 1.1, Wbemcore.exe, “is present in Windows NT Server 4.0 Service Pack 4 (CD only)”, but this installer was not part of Service Pack 5. So either snag that installer from SP4 or download WMI installer for Windows NT.

Win98, Win95
WMI installer for Windows 95 and 98
WMIC

Windows XP and newer come with a command line option called WMIC. Although older operating systems may be able to use Windows Script Host from the command line to interact with WMI, using WMIC can involve less typing. Perhaps primarily for that simple reason, WMIC can be more convenient when working on the newer operating systems.

For the most part, WMIC needs to reference an object to be useful. WMIC /? will show many of the aliases, which may be used as a reference to an object. (WMIC ALIAS LIST BRIEF may show some more.) There may be other objects available, such as if using the PATH command line option. If using WMIC PATH then either use /? (meaning “ WMIC PATH /? ”) or specify an object name. An example of such an object name may be Win32_DiskDrive.

Once an object is specified, then an action should be specified. Different objects will have different actions available. For instance, WMIC DISKDRIVE /? supports multiple commands including using either GET or LIST. WMIC PATH Win32_DiskDrive /? may show multiple other commands, including GET (optionally also using a WHERE clause) or CALL. Attempting to use a LIST command with Win32_DiskDrive (e.g. “ WMIC PATH Win32_DiskDrive LIST /?”) will result in an error, because the Win32_DiskDrive object does not support the LIST command.

UAC note

MSDN: UAC and WMI notes that UAC must be elevated the first time that WMIC is run after the operating systme is installed.

For further details about UAC, see also: UAC from command line

[#wmicinps]: WMIC in PowerShell

WMIC tends to use quotation marks and/or commas. Both of those characters may need to be escaped by a back-tick when using PowerShell.

Controlling output

By default, the output gets sent to standard output. One option, which is no big surprise, is that this output can be redirected like the standard text redirection available with any program that sends data to standard output.

There is also the /OUTPUT: switch that can specify a filename to output to. e.g.:

WMIC /OUTPUT:"wmichelp.txt" /?

Although, /OUTPUT: may has at least one specific filename reserved for a special purpose. (You can use /Output:CLIPBOARD.)

The quotation marks around the filename are often optional, but they are required if the filename contains certain characters. For example, if the filename has a hyphen, then the quotation marks are needed.

The /OUTPUT: should be an early option, mentioned even before the name of the WMI object that is going to be used.

If the file pre-exists, then it will be overwritten.

Another alternative is /APPEND:.

WMIC /APPEND:"wmichelp.txt" /?

This also outputs to a file, and was found to have the following differences from “/OUTPUT:”:

  • Output is also sent to “standard output”
    • Possibly as a result of this: WMIC may be more interactive. It may prompt after a screen of output. (The prmopt would say: Press any key to continue, or press the ESCAPE key to stop”.) This can generally be seen (with typical terminal sizes of 80x50 or 80x25) by using WMIC /APPEND"wmichelp.txt" /?
      • These prompts may also be seen in the file that gets created.
  • If the output file pre-exists, then it will be appended.
Outputing the properties of an object

Perhaps most objects may support getting the status of various “properties” of an object.

Many objects allow for a GET command. Using GET /? will show a list of properties. Then, an attempt can be made to show all properties with “GET” (by itself, without listing any specific properites) or “GET /ALL”, or a comma-separated list of individual properties can be specified. If multiple properties are specified, WMIC will show those properties in alphabetical order. Some examples of the GET command may be seen by detecting hardware.

Using GET /? might not show all of the available properties. For example, “ WMIC DiskDrive GET /? ” may not show Caption even though that is a valid property. Using “ WMIC PATH Win32_DiskDrive GET /? ” does show “Caption” as a property.

Using GET /? might show names that differ from the output. e.g., “WMIC VOLUME Get /?” shows a property called ID but if you try to actually show that, the attempt works but the field name is DeviceID. In some cases, this might provide some clue to what a shorter name means, such as the VOLUME's Automount property having the slightly longer name of Auto Mount Enabled.

If the object supports the “LIST” command, that may be a bit more likely to work than the “GET” command. For instance, using “ WMIC DISKDRIVE LIST /? ” will show the available syntaxes, and “ WMIC DISKDRIVE LIST FULL ” will show desirable results. In contrast, running “ WMIC GET ” may result in output consisting of the following message: “Invalid XML content.” (Then, after also printing a blank line, the program may quit.) Perhaps, in such a case, using GET /? may work to show a list of properties, and perhaps output can work better by excluding any specific properties that break the output.

In some cases, though, the LIST command may not be an available command. It does seem like the GET command may often be more supported. For instance, using “ WMIC PATH Win32_DiskDrive /?” shows support for the GET command, but not the LIST command. Furthermore, this object supports allowing the GET command to be affected by a WHERE clause.

Invalid XML content.

If the GET command does result in a message saying “Invalid XML content.”, then the problem might be able to be narrowed down to a single column. For instance, running: “ WMIC PATH Win32_DiskDrive GET /? ” will show a Property column. There will also be a column called “Type which describes the type of the property, and a column called Operation (which might say just the word “Read” which would indicate a read-only value). Trying various results may show that many properties can be displayed, such as running:

WMIC PATH Win32_DiskDrive GET Caption,DeviceID,InterfaceType,Signature,Size

Although that may work fine, another set of properties may show the message that says “Invalid XML content.” For example:

WMIC PATH Win32_DiskDrive GET Caption,SerialNumber

Since even extracting just the SerialNumber by itself may show that message, it can be clear which column is causing the problem. However, this doesn't always work: If using the DISKDRIVE alias instead of using PATH Win32_DiskDrive, it may be that each individual property can be output, but simply running “ WMIC DISKDRIVE GET ” (with no further parameters) may still show the “Invalid XML content.” message anyway.

[#mwmihout]: Choosing how output is displayed
Choosing a format

After specifying the properties (directly, in the case of GET, or by specifying a group/category, such as if using LIST FULL), a reference may be made to specify the desired output format.

By default, using GET will use /FORMAT:TABLE while LIST will, by default, use /FORMAT:VALUE. The output of /FORMAT:LIST seems to be identical to /FORMAT:VALUE. Using /VALUE also seems to act like /FORMAT:VALUE.

Other options may be mentioned as keywords listed in the %windir%\system32\wbem\XSL-MAPPINGS.XML file, as noted by TechNet: Creating and editing formats in WMIC. (That web page may also describe some of the options further.)

WMIC /FORMAT:HTABLE /OUTPUT:HorizTbl.htm options
WMIC /FORMAT:HFORM /OUTPUT:VrtHTMTbl.htm options
WMIC /FORMAT:"htable.xsl":"datatype=number":"sortby=propertyName" /OUTPUT:sortdTbl.htm options
WMIC /FORMAT:XML /OUTPUT:HTMLXML.htm options
WMIC /FORMAT:RAWXML /OUTPUT:RawXML.xml options
WMIC /FORMAT:CSV /OUTPUT:commasep.txt options

Those are some sample commands that represent just some of the available options.

To check which output formats WMIC supports, you can run somethign like, “WMIC VOLUME GET /FORMAT /?”. The WMIC command may try to utilize its own paging capabilities, which may corrupt the output. For instance, in Windows 10, this has been known to pause after “RAWXML”, but then once a key is pressed, fail to erase the prompt right, and end up erasing the “RAWXML” text.

For objects that support the LIST BRIEF command, that typcially is equivilent to using “GET” with a pre-defined list of some of the most popular properties. Similarly, using “LIST FULL” is like using “GET /ALL”. One difference is that the “LIST” commands may default to using the table-style of output, similar to using “GET /VALUE”.

Specifying where output goes

By defauilt, output goes to standard ouitput. So /OUTPUT:STDOUT is the default. Running “WMIC /OUTPUT /?” will show that using /OUTPUT:CLIPBOARD may also be used, and that other values will be treated like a filename. So, using WMIC /OUTPUT:"output.txt" will create a file with the specified name. The quotation marks are generally optional: “WMIC /OUTPUT /?” says (quoting Windows 7), “Enclose the switch value in  double quotes, if the value contains special” “characters”.

WMIC Best Practices states, “Commands that output in HTML” ... “typically have their output directed to a file.” Using /OUTPUT is one option. Another option would be to just let output go to standard output, but use text redirection to cause a file to be created. Using text redirection ought to work fine, although it is presumed that approach may be more prone to have error messages (that wouild be written to the “standard error” pipe/stream) be mixed with the successful output which can be less nice in some circumstances.

[#wmicwher]: Selecting

MS KB 290216 provides information to see this example:

WMIC PROCESS WHERE (ProcessID^>300) LIST BRIEF

The ^ before the > is a shell escape character. Note, however, you can do some more elaborate things using groups that use parenthesis, apostrophes, or quotation marks. In particular, if you are comparing to a value that is non-numeric, then that value should be surrounded by apostrophes or quotation marks.

Note that if you have a shell redirection character in between quotation marks, it seems like the shell does not require the redirection symbols to be escaped. (You can verify this, probably more simply, with the echo command.)

WMIC PROCESS WHERE "ProcessID>300 AND ProcessID<500" Get Name,ProcessID

Here is a similar example to help find the PID of the current shell. The usage of a percent sign acts as a wildcard, and the usage of a double-percent sign is needed as a shell escape:

WMIC Process WHERE ( CommandLine Like "%%WMICFlagSampleOne%%" ) Get ParentProcessID /FORMAT:LIST

The idea there is that WMICFlagSampleOne is unique text that won't be found on an unrelated command line. Customize that if needed. If you want to use this technique with multiple processes, you could expand that to include some random text:

WMIC Process WHERE ( CommandLine Like "%%WMICFlagSampleOne%RANDOM%%%" ) Get ParentProcessID /FORMAT:LIST

“Scripting Guy!” Forum: post about using LIKE and “Wildcards in a WMIC uninstall command” shows another example, and also indicates that an underscore may be used as a single character wildcard.

TechNet: WMIC Best Practices shows another example that looks quite a bit like this:

WMIC NTEVENT WHERE "LogFile='system' and Type>'0'" GET Message,TimeGenerated /FORMAT:htable >> sysevts.htm

(Warning: the above command may take a while. On one tested machine (which was a home machine with Win7), it took over 39 and 1/2 minutes, and generated a file that was over 30,000 KB documenting 59,008 instances. Pressing Ctrl-C would abort WMIC relatively quickly.)

So apparently the command line is presumed to understand the greater-than sign is meant to suggest “greater than”, and not redirection... at least sometimes. However, despite MS KB 290216 showing parenthesis, TechNet: WMIC Best Practices seems to suggest that parenthesis won't work, and recommend quotation marks.

Note: Also using greater-than signs as redirection was done just for demonstration purposes. Using an option like /OUTPUT may have been more appropriate. (Further testing/checking is needed for an example. Reference: TechNet: WMIC Best Pracices.)

[#wmicrmot]: Remote usage of WMIC

e.g.:

WMIC /NODE:"compname" /?
WMIC /NODE:"compname" NIC LIST /FORMAT:LIST

Or, MS KB290216 indicates multiple computers may be specified, comma separated. So:

WMIC /NODE:"compname","namecomp" NIC LIST /FORMAT:LIST

TechNet: “WMI Isn't Working!”, section titled, “I can’t connect to a remote computer” says, “WMI uses the DCOM (Distributed COM) and RPC (Remote Procedure Call) protocols to traverse the network. By default, many firewalls block DCOM and RPC traffic” ... “For example, the Windows Firewall found in Microsoft Windows XP Service Pack 2” will “block” ... “DCOM and WMI: in its default configuration”. (Hyperlink(s) added to quoted text.)

The same TechNet article also indicates that having local Administrator privileges on the remote machine will typically be necessary (unless a less common workaround enables such remote access).

TrustedSec.com : “We Don't Need No Stickin' PSExec” says, “The initial WMI communications use TCP port 135 and afterwards a random port is negotiated.”

Using /FAILFAST may be desirable. (See: MSDN: WMIC command line options. May not work as well with Windows XP prior to SP1, as described by MS KB 824223.)

[#wmicevry]: Repeating
e.g., An example shows /EVERY:5 to re-run a query every 5 seconds. WMIC will temporarily write “Hit any key to break the cycle....” (and then will erase that output before running the next iteration).
Some other commands to interact with WMI

In Windows 98 Second Edition, WBEM was an optional component. If it was installed, there were some commands that could be used to interact with WMI.

TechNet: Verifying the State of the CIM Repository provides some VBScript. There are some spacing issues with the code as shown on that web page: These spacing issues are corrected in the slightly modified versions provided here. MS WMI Code: Class Count (modified to be more verbose), MS WMI Code: Namespaces, MS WMI Code: Providers. The Class Count may appear to freeze up, but interestingly it may run much faster the second time that it gets run.

[#wmicode]: Programmer's notes: How to interact with WMI
Using WMI from within Windows Script Host
WMI from JavaScript

Keep in mind that WMI is a form of WBEM. So, a solution for interacting with WBEM in JavaScript is effective in handling WMI in JavaScript.

[#wmivbs]: WMI from VBScript

No particular guide is currently available here, but see Corrolating Disk to Device Names: Sample VBScript for an example. Also, compare with the documentation for JavaScript.

Finding available WMI providers
Namespaces

Rob van der Woude's Scripting Pages: WMIC (a page by somebody of no known close relation to the Mr. VanderWoude who created this ][CyberPillar][ website) notes, “Use WMIC's /NameSpace:\\root\other_namespace switch to query classes that are not located in the default CIMV2 namespace.”

Creating Hierarchies within WMI discusses namespaces.

WMIC /?

shows some available aliases.

WMIC Alias LIST BRIEF

shows some available aliases. That seems to be equivilent to:

WMIC Alias Get FriendlyName,PWhere,Target

WMIC Alias get /?
WMIC Alias get Connection,Description,FriendlyName,PWhere,Qualifiers,Target,Verbs /FORMAT:LIST
WMIC Alias get Connection,Description,Formats,FriendlyName,PWhere,Qualifiers,Target,Verbs

MSDN: Windows Management Infrastructure (“WMI”) / “Open Management Infrastructure” (“OMI”) / Management Instrumentation (“MI”) / Managment Object Format (“MOF”) details lists various pieces of software, called “WMI providers”, that provide details that can be accessed from WMI.

WMI Classes is also mentioned by “TechLe007”'s answer to Mehrdad's SuperUser.com question on available WMI providers/paths/classes. “TechLe007” also noted how the PowerShell command “Get-WMIObject -list” can be used (with output piped into some other commands) to generate a list.

A sample

WMI Registry | WMI Persistence using wmic.exe has this:

WMIC /NAMESPACE:\\root\CIMV2" PATH Win32_ComputerSystem GET /all /FORMAT:list
Calling code

It looks like the following may show some available entry points.

WMIC alias GET Description,FriendlyName,PWhere,Qualifiers,Target,Verbs /FORMAT:LIST
Coding with WBEM
[#wbemjs]: Using JavaScript to interact with WBEM
WBEM in Microsoft Windows

The following code originated from Merlyn Morgan-Graham's post at StackOverflow.com, but has been adapted so more clearly show some individual pieces.

var strServer;
var strNamespace;
var loc;
var svc;
var coll;
var collItems;
var strWbemObjName;
var strSQLQuery;

strServer = ".";
strNamespace = "root\\cimv2";
strWbemObjName = "Win32_Process";
strSQLQuery = "Select * from " + strWbemObjName;
loc = new ActiveXObject("WBemScripting.SWbemLocator");
svc = loc.ConnectServer( strServer , strNamespace);
coll = svc.ExecQuery( strSQLQuery );
collItems = new Enumerator( coll );

while (!collItems.atEnd())
{
WScript.Echo(collItems.item().Name);
collItems.moveNext();
}

That is the short version. The following version accesses objects in a more detailed fashion, and outputs quite a bit more (unless bShowAllProperties gets set to false). It is also based on some JavaScript code by Helen at StackOverflow for accessing WMI properties.

var strServer;
var strNamespace;
var strSQLQuery;

var loc;
var svc;

var strWbemObjName;

var collWbemProps; // collection
var collWbemPropsEnum; // used to help keep track of current object
var currWbemProp; // Used to shorten code; refers to what Enum is tracking.

var strMsgToOutput;

var WbemPropsObjJSProps;
var WbemPropsObjJSPropsEnum;
var strCurrWbemPropName;

var bShowAllProperties;
var currWBemPropJSProp;

// The following has high likelihood of being desirable to customize
strServer = ".";
strNamespace = "root\\cimv2";
strWbemObjName = "Win32_Process";
strSQLQuery = "Select * from " + strWbemObjName;


loc = new ActiveXObject("WBemScripting.SWbemLocator");
if(loc)
{ svc = loc.ConnectServer(strServer,strNamespace);
collWbemProps = svc.ExecQuery( strSQLQuery );
collWbemPropsEnum = new Enumerator( collWbemProps );

while (!collWbemPropsEnum.atEnd())
{ WScript.Echo("===New WBEM Property===");
currWbemProp = collWbemPropsEnum.item();

// The following chunk of code outputs the value of a specific property.
// Most/all WBEM Properties have both a name and a value.

// For example, if these WBEM Properties are related to the WMI
// object called PROCESS, then there is a WBEM Property that has
// a name of "Description".  (The value of that property can then
// be used to identify a specific PROCESS.

strCurrWbemPropName = "Description";

// Other WMI objects might not have a property named Description.
// Many WMI objects may have a property named Name.
// So, the next line could be useful.
// strCurrWbemPropName = "Description";

StrMsgToOutput = "";
StrMsgToOutput = strMsgToOutput+"Property "+strCurrWbemPropName;
StrMsgToOutput = strMsgToOutput+" is ";
StrMsgToOutput = strMsgToOutput+strCurrWbemPropName[strCurrWbemPropName];

WScript.Echo(StrMsgToOutput);


// The above code works great when the name of the WMI property is
// known.
// However, what if we don't know the name of a specific WMI property?
// Experienced JavaScript coders may assume that the properties can be
// accessed using for(var idx in someObject). However,
// http://stackoverflow.com/a/974118 states,
// "JScript's for...in statement isn't compatible with WMI objects,
// because, well, they are more complex than native JScript objects."
// So the expected approach will not work.  The following workaround
// seems fairly complicated, but does achieve the task of showing the
// names of all of the WBEM Properties.


bShowAllProperties = true; // Optional, much more verbose output
if(bShowAllProperties)
{ // The result is far more verbose.

WbemPropsObjJSProps = currWbemProp.Properties_;
// (Note: Properties_ has a required underscore after the word Properties.)
// Each WBEM Property has a bunch of JavaScript properties.
// Yes, that means that the properties have properties.
// Commonly/always true will be the following:
// Each WBEM Property will have a JavaScript property called Name
// Each WBEM Property will have a JS property called Value

// To elaborate (hopefully clarifying) - WbemPropsObjProps is an
// object that contains WBEM Properties.  For example, if the
// query returned a bunch of DISKDRIVEs, each WBEM property may
// be a separate DISKDRIVE.  Then, each DISKDRIVE may have its
// own properties.  Since the WBEM property is the DISKDRIVE,
// this means that the WBEM property has properties.

WbemPropsObjJSPropsEnum = new Enumerator( WbemPropsObjJSProps );

while(!WbemPropsObjJSPropsEnum.atEnd())
{ currWbemPropJSProp = WbemPropsObjJSPropsEnum.item();
strCurrWbemPropName = currWbemPropJSProp.Name;

strMsgToOutput = "";
strMsgToOutput = strMsgToOutput + "Prop";
strMsgToOutput = strMsgToOutput + currWbemPropJSProp.Name;
strMsgToOutput = strMsgToOutput + " is set to [";
strMsgToOutput = strMsgToOutput + currWbemPropJSProp.Value;
strMsgToOutput = strMsgToOutput + "]";

WScript.Echo(strMsgToOutput);

WbemPropsObjJSPropsEnum.moveNext();
} //end while that loops through WbemPropsObjJSPropsEnum
} //end if(bShowAllProperties)

collWbemPropsEnum.moveNext();
} //end while that loops through collWbemPropsEnum
}
else
{ WScript.Echo('ActiveX object "WBemScripting.SWbemLocator" not created.');
}

For more details about the objects used:

  • MSDN: SWbemLocator has some example code.
  • MSDN: Creating a WMI Script (Windows) specifies that ConnectServer does not require a second parameter. If unspecified, the value will be taken from “HKLM\SOFTWARE\Microsoft\WBEM\Scripting\Default Namespace” which has a default value of \\root\cimv2

    The web page also has some example code.

  • MSDN: SWbemLocator (using this object is documented to require Windows 2000, or presumably XP or newer. Perhaps that is due to Win9x/ME not having WMI installed by default; perhaps this works if WMI is installed?) (uses dynamic link library Wbemdisp.dll and type library Wbemdisp.tlb)
  • MSDN: SWbemLocator.ConnectServer

At the time of this writing, this has not been tested by the author of this text. However, it does seem likely, since WMI can be accessed in VBScript, and JavaScript can make objects as well. An example of using Objects in JavaScript may be seen by SAPI 5.1 ActiveX (although that does use older versions).

WBEM for VBScript

See: WMI in VBScript.