Command Line Standard
This document is focused at developers of command line utilities. Collectively, our goal is to present a consistent, composable command line user experience. Achieving that allows a user to learn a core set of concepts (syntax, naming, behaviors, etc) and then be able to translate that knowledge into working with a large set of commands. Those commands should be able to output standardized streams of data in a standardized format to allow easy composition without the burden of parsing streams of output text. This document is written to be independent of any specific implementation of a shell, set of utilities or command creation technologies; however, Appendix J - Using Windows Powershell to implement the Microsoft Command Line Standard shows how using Windows PowerShell will provide implementation of many of these guidelines for free.
On This Page
Introduction
Summary List of Guidance
Details
Command Name Example
Navigating and Operating on Namespaces
Appendix A - Standardized Verb Sets and Verb Names
Appendix B - Standardized Parameters
Appendix C - Standardized Error Message Templates
Appendix D - Standardized Globbing
Appendix E - Standardized Data Example
Appendix F - CliXmlDataStream Data Schema
Appendix G: Navigation Examples
Appendix H: Standardized Help Tags
Appendix I: Win32 Code to Write Output
Appendix J - Using Windows PowerShell to implement the Microsoft Command Line Standard
Appendix K - Error Record Schema
Appendix L - Enhanced Interoperability Guidance
Appendix M - Typed-CSV (TCSV) Data Format
Appendix N - Argument Parsing Pseudo code
Introduction
In order to provide a consistent, composable user experience, across a wide range of commands, this document provides guidance on:
Consistent verb and parameter naming conventions.
Consistent command syntax
Common behaviors.
Consistent error messages and exit codes.
Schema-enhanced data-streams and formatting.
This document builds upon the traditional command line compositional model. That traditional model had the following three characteristics:
Commands are standalone processes that accept a sequence of text parameters (that might have been typed on a command line), accept data from STDIN, write results to STDOUT, write error messages to STDERR, and exit with a code indicating success or failure.
Commands are focused on performing specific operations. The user composes a sequence of commands to implement a task or user-scenario.
Composition is achieved by picking out the important elements of one command’s output and providing as parameters or data to another command.
If you create command-line tools that have these three characteristics, you will have achieved UNIX level interoperability. Building upon that, there are Enhanced and Optimal levels of interoperability. This document primarily focuses on the Optimal level of interoperability, but guidelines for Enhanced interoperability are available in Appendix H - Enhanced Interoperability Guidance . Enhanced interoperability provides a stepping stone for existing commands. As a first step, you can elevate them to Enhanced interoperability on the way to achieving Optimal interoperability.
This document is structured as a progressive disclosure: The Summary List of Guidance section is a two page summary. The Details section provides details and background for each guideline in the summary. The Appendixes provide reference material necessary to implement the guidelines.
Summary List of Guidance
Command Names
Required:
- Command names must be well-formed names consisting of a noun and a verb in the form: verb-noun.
Verbs
Required:
- Commands must use verbs from the list of standard verbs in Appendix A.
Recommended:
- Developers should implement as many verbs in the defined Verb groupings (Verb Sets) as makes sense for their feature.
Noun Names
Recommended:
Commands should avoid using the noun names Windows PowerShell has reserved (See Section 3.3 Nouns).
Commands should use their product or feature name (or abbreviation) to prefix their noun.
Consistent Syntax
Required:
- Commands must use the “-“ character for parameter delimitation; a colon (:) or whitespace to separate the parameter name and its arguments and a comma (,) to separate multiple values within an argument.
Input
Required:
- Commands must accept text or CliXml input (using CliXmlDataStream Schema defined in Appendix E - Standardized Data Schema ) in STDIN.
Recommended:
Commands should accept Typed-CSV (TCSV) input in STDIN.
Commands should provide a -InputFormat [XML | TCSV | TEXT ] parameter to allow the user to identify what type of data will be coming in on STDIN.
Parameters
Required:
Commands must support -?, -Help, -Version, -Verbose, and -Debug for all commands.
Commands must support -WhatIf and -Confirm for any operation which has a side-effect.
Commands must support -ErrorAction to determine behavior when errors occur.
Parameter names must be case-insensitive.
Passwords must not be accepted as a parameter argument.
Recommended:
Commands should choose parameters from the standards specified in Appendix B.
Commands should support -SelectProperty to specify which properties to output on STDOUT.
Commands should allow the user to specify just enough of a parameter name to disambiguate it from other parameter names and provide a one or two character shortcut to specify a verbose parameter name.
Commands should document their parameter names using Pascal casing rules (capitalize the start of every word).
Targeting
Recommended:
Commands should use wildcard expansion for input globbing (Appendix D - Globbing).
Commands should use common parameters for specifying the target of a command (e.g. -Name, -ID, -File, -ComputerName) .
Commands should support multi-value targets as well as the -Include and -Exclude parameters.
Commands should support the -Filter parameter to specify a domain-specific query or filter.
Output Formatting
Required:
Output must be written using the logic illustrated in Appendix I: Win32 code to write output to properly address globalization requirements.
Commands must support the -OutputFormat parameter to allow users to specify their desired format and the -OutputPreamble to configure schema enhanced data streams
Commands must use the value of the environmental variable CliDataStreamSchema when -OutputFormat is not specified.
Commands must support at least one format of schema-enhanced dataStreams (TCSV or CliXml).
Recommended:
Commands should support CliXml Appendix F - CliXmlDataStream Data Schema and Appendix K - Error Record Schema and tag which stream (DEBUG, ERROR, OUTPUT VERBOSE, or WARNING) the data came from. Commands must output CliXml when the environmental variable CliXmlStreams is set to TRUE. Commands must output XML using CliXmlDataStream schema.
Commands should support other XML schemas where there is a community of tools that will consume that output (e.g. CimXml).
Exit, Errors, and Others
Required:
Error messages (as well as VERBOSE and DEBUG messages) must be written to STDERR.
Commands must terminate with an exit code indicating success (0) or failure (non-zero).
Recommended:
Commands should use the exit codes and standardized error messages defined in Appendix C. Augment those standardized error messages with specific detailed error messages.
Commands should tell the user (on STDERR) the Syntax of a command if they specify a syntactically invalid command.
Details
3.1 Command Names
Command names must be well-formed names consisting of a noun and a verb in the form: verb-noun. Each noun will specify a specific part of the system to operate on. For example, the “Service” noun operates on Windows Services. The operations (or actions) are defined by the verbs. For example, we can “Start” a Service or “Stop” a Service. The command names for these operations are: “Start-Service” and “Stop-Service”. (Note the use of the “-” character to separate the verb and noun.)
3.2 Verbs
Commands must choose a verb from the list of standard verbs in Appendix A. Verbs are the backbone of a consistent user experience. The user should be able to perform 80-90% of all operations on the system using fewer than 50 verbs. Administrators can learn those 50 verbs and then make successful guesses about what to type when they need to perform a new operation or they encounter a new object. Suppose we have lots of types of things running on a system: Processes, Services, WebServices, BackUpJobs, Disks etc and that the user wants to stop them. We standardize on the verb Stop. The resultant commands are Stop-Process, Stop-Service, Stop-WebService, Stop-BackupJob, Stop-Disk etc. Notice that our desire to manage everything with fewer than 50 verbs causes us to make some difficult decisions. “Kill” is the traditional verb for processes, “cancel” has a nuance that is different from stop, “terminate” might be a more appropriate for particular nouns. All of these considerations seem important when you look at a single noun. However, to deliver an admin-coherent system, we must converge on a small set of verbs.
Note
Parameters can be used to provide more precision or specificity to a verb. For example, “Stop-WebService -Drain” could be used to indicate that existing work items should be completed before stopping the service (a new verb is not required).
Fifty verbs are still quite a few to learn and remember. To facilitate learning and increase retention, we put them into defined groupings called “Verb Sets” and associate most verbs with a corresponding PAIR verb (e.g. Start pairs with Stop, Get pairs with Set).
The verb sets are:
Common Object Verbs Some of these will be used with almost every noun. For example, many nouns will support the “New” and “Remove” verbs.
Data Verbs These are used with data intensive operations and include “Compare” and “Merge”.
Lifecycle Verbs These are envisioned to be used with activities. The lifecycle verbs include “Start”, “Stop” and “Resume”.
Diagnostic Verbs As the name implies, these are for diagnostic purposes. The set includes “Measure”, “Test” and “Debug”.
Communications Verbs This set includes “Send” and “Receive”.
The complete list of Verb Sets is in Appendix A - Standardized Verb Sets and Verb Names. Developers should implement as many verbs in the defined Verb groupings (Verb Sets) as makes sense for their feature. Users will learn and remember the verbs in sets. If you support a particular verb, they will guess that you’ll support more verbs in that set (e.g. if you support Stop, you should probably support Start and, perhaps, Suspend and Resume).Note that in most cases a particular noun will use verbs from more than one verb set. At the same time, most nouns will not use all the verbs in any one set.
3.3 Noun Names
Commands should avoid using the nouns Windows Powershell has reserved. Nouns identify the type of object being operated upon. As a general rule, each feature team will pick their own noun names and standardization will be limited to common sub noun names. Avoid using nouns that Windows Powershell will use. If your command uses one of these reserved nouns, it is likely that customers will need to use the full pathname to your command. This is the list of generic nouns that Windows Powershell has reserved:
Alias |
ChildItem |
Cmdlet |
Command |
Content |
Drive |
History |
Item |
List |
Location |
Object |
Path |
Property |
PropertyValue |
Provider |
RunSpace |
Table |
Variable |
PS* |
Commands should use their product or feature name (or abbreviation) to prefix their noun. Many teams will have similar noun names. For instance, many database teams might create the command “new-table”. To avoid collisions, it is best to prefix common noun names with the product or feature name. e.g. “New-SqlTable”
3.4 Consistent Syntax
Here is an example of the standard Command Line Interface (CLI) syntax:$ Verb-Noun -Parameter1 Value1 -Parameter2 Value2,Value3,Value4Commands must use a dash (-) for parameter delimination; a colon (:) or whitespace to separate the parameter name and its arguments and a comma ( ,) to separate multiple values within an argument. More formally, commands should support the following syntax:
<command> := <commandName> <parameterOrArgument>* ['-' <argumentString>*]
<parameterOrArgument> :=
<dash><parameterName> <space>+ <argumentString> |
<dash><parameterName> ‘:’ <space>* <argumentString> |
'-'<parameterName> |
<argumentString>
“*” means 0 or more.
+” means 1 or more.
<dash> can be any of ASCII dash (0x002d), endash (0x2013), emdash (0x2014) or horizontal bar (0x2015).
<parameterName> is any sequence starting with an alpha character followed by zero or more alphanumeric characters.
<argumentString> is any sequence of characters.
See Appendix N - Argument Parsing Pseudo code for details on how to implement a compliant argument parser. Quoting is not addressed by this grammar as it is handled by the invoked application. In general though, it is assumed that there is some mechanism to allow argument strings to contain arbitrary characters including spaces. A parameter name without a trailing ‘:’ must both match the syntactic requirements (i.e. start with a dash) and be recognized by the command as a valid parameter. If the token is not recognized as a valid parameter, it shall be treated as an argument if appropriate. A parameter of the form -name: must be followed by an argument.A parameter of the form -name (no trailing colon) must be followed by an argument except in the case were the parameter is considered to be a Switch parameter. In this case no argument is required and the presence of the parameter is to be treated as though it were given an explicit argument of true. If you wish to pass a false value to a Switch parameter, the -name: pattern must be used. The sequence ‘—‘ (dashdash) indicates the end of parameters. All tokens after dashdash will be treated as arguments.
3.5 Input
Whenever possible, design your command to operate over a set of data instead of a single data instance. This allows better composition of command sequences which reduces the need for admin programming and simplifies error reporting and handling.Commands must accept text or CliXml input (XML using CliXmlDataStream Schema defined in Appendix E - Standardized Data Schema ) in STDIN. The typical way to achieve this is to read text from STDIN and process it as data records. In addition to this, you should allow data records encoded in XML from STDIN. Commands should accept Typed-CSV (TCSV) input in STDIN. When processing text data records from STDIN, you might need to specify syntax to allow multiple fields. TCSV records are the preferred way to achieve this. See Appendix M - Typed-CSV (TCSV) Data Format for a definition of this data format.Commands should provide a -InputFormat [XML | TCSV | TEXT ] parameter to allow the user to identify what type of data will be coming in on STDIN. If you allow multiple types of input, you’ll need a way to allow the user to specify what type of input they have provided. Use the parameter -InputFormat which takes a KEYWORD to accomplish this.
3.6 Parameters
Providing a common, consistent set of parameters across commands is necessary to provide a good user experience. Reducing the number of verbs in command names means that parameters will be used to specify more precise operations. Providing a common set of parameters with consistent semantics provides users with ready solutions to common problems.
Commands should choose parameters from the standards specified in Appendix B. Standardized Parameters : A set of common parameters has been standardized to:
Refine the meaning of a verb. (e.g. -At -After and -Before are used with the verb “Add” in place of the verbs “Append”, “Attach”, “Concatenate” and “Insert”.)
Specify a date time related parameter (e.g. -Modified, -Before -Since)
Request a format (e.g. -Encoding, -Width, -Wrap)
Specify a common property or resource (e.g. -Count, -Description, -Name)
Specify a quantity (e.g. -All, -Count, -Scope)
Users, like CSS for example, need to quickly tell what specifically they are working with and what its capabilities are. They need visibility into what it is doing and how it is doing it. All commands must support -?, -Help, -Version, -Verbose and -Debug.
-? - provide help about this command. When outputting this data in XML format, use the tags in Appendix H: Help Tags. Data goes to STDOUT.
-Help - same as -?.
-Version - tell the user what version of the command they are running, what company produced the command and what product it was shipped in. Data goes to STDOUT.
-Verbose - provide user-level information about what each operation is doing. Data goes to STDERR.
-Debug - provide CSS/Developer-level information about what is happening. Data goes to STDERR.
Administrators need a command line environment which allows them to tell what is going to happen before they commit themselves. Commands must support -Whatif and -Confirm for any command which has a side effect.
Confirm - ask the user before doing any operation which has a side effect (i.e. the operation modifies the system. In general, GETS do not have side effects but SETS do). The prompt should be issued to STDERR and take the following form:Continue with this operation?stop-process on CcmExec () #Specify your operation on this line[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help :
WhatIf - tell the user what operation would have occurred but don’t do the operation. This information should go to STDOUT and each line should start with the comment char ‘#’ to indicate that the operation did not occur. .e.g# stop-process on lsass
Users need fine control over what happens when things go wrong. This is especially important when operating on sets of input. Sometimes the user will want to continue processing, other times they’ll want to stop. Commands must support -ErrorAction to determine behavior when errors occur. This must take the following values:
Continue - Issue a non-terminating error and continue processing.
Stop - Issue a terminating error and stop the command.
Inquire - Issue an error and ask the user whether to continue processing or stop. Use the same prompt as -Confirm.
SilentlyContinue - Suppress error message and continue processing. The default value should be Continue.
Windows is a case-preserving, case-insensitive platform. This should be reflected in our processing of parameter names. Parameter names must be case-insensitive.
You must not encourage unsafe scripting practices such as storing passwords in clear text in script files. Passwords must not be accepted as parameter arguments.
Outputting objects in XML format can sometimes be quite verbose. Commands should support -SelectProperty to specify which properties to output on STDOUT. SelectProperty should take a list of property names to output.
Commands should allow the user to specify just enough of a parameter name to disambiguate it from other parameter names and provide a one or two character shortcut to specify a verbose parameter name. Verbosity is a user’s friend when reading a script and their enemy when typing during an interactive session. We need to support both. You need to support verbose parameter names, so start by defining those. Next, consider supporting a well-defined 1 or 2 letter name (a parameter alias) for the same parameters. For example, “-File” could also be “-F”
If the only parameter starting with “F” was “-Filename”, you would allow the user to type any of the following and recognize it as -FileName:
-Filename
-Filenam
-File
-Fi
-F
(Some skipped for the sake of brevity.)Commands should document their parameter names using Pascal casing rules (capitalize the start of every word). For example, . -SelectProperty. This makes it easier to read.
3.7 Targeting
Most commands are targeted at an object or a set of objects. For instance, Stop-Process targets a process or a set of processes. Copy-File targets a file or set of files. The purpose of many existing scripts is to get the right set of objects to operate on and to pass them to a command. Many scripts could be eliminated and many more could be made simpler by providing a common, rich model for specifying the target of a command.
Commands should use common parameter names for specifying targets (e.g. -Name, -Id, -Location, -File, etc).
Commands should use wildcard expansion for input globbling (Appendix D - Globbing;). (e.g. lsa*, *.txt, [a-c]*). Use the back-quote character ‘`’ as an escape character if this is required for your resource.
Commands should support multi-value targets as well as the -Include and -Exclude parameters. Multi-value targets should be separated by commas (,) (e.g. -Name a,b,c,d*,e ). Use -Include to identify things that should be included in the target list. Use -Exclude to identify things to eliminate from that target list. For example, to get all files that start with “a” that are not XML or CS files: -File a* -Exclude *.xml,*.cs.
Note
The semantics of -exclude should be to eliminate items from a list of things about to be operated upon. In other words, it must be evaluated AFTER the other targeting rules.
Commands should support the -Filter parameter to specify a domain-specific query or filter.
3.8 Output Formatting
Commands must standardize the way they output results to provide a common user experience and to facilitate command composition. Composing multiple commands means that commands must output results using a common schema that is easily detected so that the output can be processed to feed into other commands. Output must be written using the logic illustrated in Appendix I: Win32 code to write output to properly address globalization requirements.
Many commands will choose to output data in multiple formats. At a minimum, they must be able to output programmatic-friendly, schema-enhanced data streams. Schema enhanced data streams start with a Preamble indicated by the character sequence “#< “ followed by the name of the data schema in use (e.g. CliXml, TCSV, etc). The preamble can optionally continue with multiple lines of the format “# NAME VALUE”. These lines can provide additional information about the data such as when, where, and by whom it was created. The preamble is terminated with a blank line and followed by the body.
Many of today’s scripts are all about outputting the data in different formats or parsing the output to manipulate the data and output or act upon it. To support a rich scripting environment. Commands must support the -OutputFormat parameter to allow users to specify their desired format and the -OutputPreamble to configure schema enhanced data streams.
Standard values for -OutputFormat are:
TCSV
HTML
LIST
TABLE
WIDE(Output only the Name or ID in multiple columns.)
CLIXML
Standard values for -OutputPreamble are:
NONE (This allows CLIXML data to be processed as text)
BRIEF (Single line indicating schema)
FULL (multiple lines providing additional data about the data)
Note
-OutputPremable only applies to some OutputFormats (e.g. CliXML and TCSV).
Commands must use of the value of the environmental variable CliDataStreamSchema when -OutputFormat is not specified.
Commands must support at least one format of schema-enhanced dataStreams (TCSV or CliXml).
Commands should support CliXml Appendix F - CliXmlDataStream Data Schema and Appendix K - Error Record Schema and tag which stream (DEBUG, ERROR, OUTPUT VERBOSE, or WARNING) the data came from.
Commands must output CliXml when the environmental variable CliXmlStreams is set to TRUE. Commands must output XML using CliXmlDataStream schema.
Users want uniform control over what information is displayed when and fine control over that information. Developers must analyze the data that they are outputting and tag it with the “virtual stream” tag. The OUTPUT virtual stream will be emitted on STDOUT and all others will be emitted on STDERR. Developers can output anything on any virtual stream except the ERROR stream. The ERROR stream must emit error records in the schema defined in Appendix K - Error Record Schema.
Virtual Stream Definitions:•
DEBUG - Developer-focused activity/information (not localized).
ERROR - Messages indicating the failure to process a record or object (localized).
OUTPUT - Results of successful processing (localized).
VERBOSE - User-focused activity/information (localized).
WARNING - Processing irregularity occurred (able to complete the operation but something could be off) (localized).
3.9 Exit, Errors, and Others
To facilitate command composition, the only thing that should be output on STDOUT is command results. Error messages (as well as VERBOSE and DEBUG messages) must be written to STDERR. When scripting with commands, the admin has to know whether a command succeeded or not. Commands must terminate with an exit code indicating success (0) or failure (non-zero).There are existing Microsoft standards for the generation of error messages which provide guidance about such things as being very specific, providing recovery actions etc. Those are all good guidelines and you should follow them. They do however produce a problem for the command line user. Most command line users want to operate on the level of recognition vs. reading. They’ll want a verbose error message long enough to understand the issue and then they’ll want a pithy message that they can recognize and respond to. Commands should use the exit codes and standardized error messages defined in Appendix C. Augment those standardized error messages with specific detailed error messages. One of the most common errors that will occur is getting the command line syntax wrong. Commands should tell the user (on STDERR) the syntax of a command if they specify a syntactically invalid command.
Command Name Example
Assume we have a feature named “Burp”. The main component of our feature is a service. We decide to use our feature name as part of the noun, so that we end up with the noun “BurpService”.
As we look over the verb tables we see that the lifecycle verbs match most of our basic control needs. For our service we need:
Disable
Enable
Install
Restart
Start
Stop
Uninstall
After careful examination we note that our service can not be suspended so we don’t need the “Suspend” and “Resume” verbs. We also may note that in a previous service, that our new BurpService is modeled on, we used “kill” to stop the service. Looking at the tables, we decide that stop conveys the same meaning to the user so we decide to use the verb “Stop” instead of “Kill”.
Next we look at the common object verbs. Notice that for the BurpService we can retrieve and set useful information. In the past we might have used “Find” and “Write” but when we search for this, we see that these verbs are not in the list and that the correct verbs to use are “Set” and ”Get”.
Thus we end up with the command names: Disable-BurpService, Enable-BurpService, Install-BurpService, Restart-BurpService, Start-BurpService, Stop-BurpService, Uninstall-BurpService, Get-BurpService, and Set-BurpService.
Navigating and Operating on Namespaces
There is a set of commands that are important enough to warrant special attention, namely the commands to navigate and operate on namespaces. The most familiar example of this is navigating Filesystems (e.g. cd, pushd, popd) and operating on files (e.g. cat, rm, mkdir). There are many other namespaces such as WMI, AD, Registry, XML, etc. If you provide an interactive utility which navigates a namespace, you should provide an implementation of the following common model.
A namespace is a named set of objects organized into a hierarchy. That hierarchy is called a Drive. The hierarchy is comprised of a set of Locations identified by strings call Paths. The syntax for a Location is “Drive:Path”. At each location there can be one or more of the following elements: ChildItem, Item, Property, Content, Permission, Relation. See Appendix G: Navigation Examples
Note that the model makes no attempt to standardize the syntax for a Path or the data structures for any of the elements. The properties and content of a REGISTRY location are very different from that of a Filesystem or an XML document. The syntax for an AD path is very different from a Filesystem (children are appended to the left with a “,” delimiter).
With this basic model in place, we can apply the rest of the command line standard to produce a set of commands to navigate and manage any space. See Appendix G for a table of commands and their Filesystem equivalents. Notice that the targets of the commands can be relative or absolute (e.g. Get-Content c:\Burp\bar.txt or Set-Location c:\Burp;Get-Content bar.txt )
Appendix A - Standardized Verb Sets and Verb Names
The following table is organized as follows:
The leftmost column is the list of verbs, followed by a column with the verb definition.
The “common parameters” are the parameters most often used with that verb. Note that not all parameters in the list will be supported for each verb. For example when removing a file it may not be necessary to support an “-Erase” option. However, there may be times when security, or other reasons, dictates that the item not just be removed from the system, but that the bits be erased. In that case, the preferred parameter is “-Erase”.
The next column lists the “obsolete” verbs. Recall that earlier it was noted that one of the goals is to converge the language used to administrate a system to a set of well-understood, common terms. Part of that effort requires obsolescing some of the words that could be used to imply the same operations.
The last column is the pair of the verb. While not required, often times when a noun supports a verb, it will also support the pair.
Note that there are several verb tables. The first, the “common object verbs”, are the verbs that will be used with most nouns. As noted previously, any one noun probably will not support all the verbs in this set. However, all nouns will probably support some of these.
The other verb sets are more specific to a particular type of noun or a particular activity. These include data verbs, lifecycle verbs, diagnostic verbs, and communications verbs.
Common Object Verb Set
Common object Verbs |
Definition |
Common Parameters |
Obsoletes |
Pair |
Add |
Add, append or attach an element |
At, After, Before, Create, Filter, Force, ID, Name, Value |
append, attach, concatenate, insert |
Remove |
Clear |
Remove all the elements or content of a container |
flush,erase, release, unmark, unset,nullify |
||
Copy |
Copy a resource to another name or another container |
Container, Destination, Overwrite, Recurse, Strict |
duplicate, clone, replicate |
|
Get |
-object -content -ChildItem |
All, As, Compatible, Continuous, Count, Encoding, Exclude, Filter, Include, ID, Interval, Name, Path, Property, Recurse, Scope, Sortby |
read, open, cat, type, dir, obtain, dump, acquire, examine, find, search |
Set |
Lock |
Unlock |
|||
Move |
Move a resource |
transfer, name, migrate |
||
New |
create a new resource |
Description, ID, Name, Value |
create, generate, build, make, allocate |
Remove |
Remove |
Remove a resource from a container |
(Get), Drain, Erase, Force |
delete, disconnect, detach, drop, purge, flush, erase, release |
Add/New |
Rename |
Give a resource a new name |
|||
Set |
-object -content -ChildItem |
Passthru, |
write, reset, assign, configure |
Get |
Unlock |
Lock |
Data Verbs |
Definition |
Common Parameters |
Obsoletes |
Pair |
Checkpoint |
Create a snapshot of the current state of data or configuration so that it could be Restored later |
Description, Name, Scope |
Diff |
Restore |
Compare |
Compare this resource with another one and produce a set of differences |
Diff |
||
Convert |
Change from one encoding to another or from one unit base to another (e.g. feet to meters) |
|||
Export |
Make a copy of a set of resources using an interchange format |
(get), Add, As, AsScript, Delete, Description, FileName, Location, Strict, Whatif |
extract,backup |
Import |
Import |
Create a set of resources using an interchange format |
FileName, Location |
bulk load, load |
Export |
Initialize |
Prepare a resource for use. Assign a beginning value to something |
erase, renew, rebuild, reinitialize, setup |
||
Limit |
Limit the consumption of a resource or apply a constraint on a resource |
quota |
||
Merge |
Take multiple instances and create a single instance |
coalesce |
||
Restore |
Rollback state to a predefined snapshot/checkpoint |
Checkpoint |
||
Update |
update or refresh a resource from a source of truth |
refresh, renew, recalculate, reindex |
Lifecycle Verbs |
Definition |
Common Parameters |
Obsoletes |
Pair |
Disable |
Stop and/or configure something to be unavailable (e.g unable to not start again) |
Enable |
||
Enable |
Configure to be available (e.g. able to start) |
Disable |
||
Install |
Settle in an indicated place or condition (optionally initializing for use) |
setup, load |
Uninstall |
|
Restart |
Terminate existing activity and begin it again (with the same or checkpointed configuration) |
recycle |
||
Resume |
Begin an activity again after it was suspended |
Suspend |
||
Start |
Begin an activity |
launch, initiate, boot |
Stop |
|
Stop |
Discontinue or cease an activity |
end, kill, terminate, cancel |
Start |
|
Suspend |
Suspend an activity temporarily |
pause |
Resume |
|
Uninstall |
Install |
Diagnostics verb |
Definition |
Common Parameters |
Obsoletes |
Pair |
Debug |
Interact with a resource or activity for the purpose of finding a flaw or better understanding of what is occurring. |
|||
Measure |
calculate/identify resources consumed by a specified operation or retrieve statistics about a resource |
|||
Ping |
Determine whether a resource is alive and responding to requests |
|||
Resolve |
Map a shorthand name will be bound to a long name |
where, which |
||
Test |
Verify the operational validity or consistency of a resource |
diagnose, verify, analyze, salvage |
||
Trace |
Trace activities performed by a specified operation |
Communications |
Definition |
Common Parameters |
Obsoletes |
Pair |
Send |
Convey by an intermediary to a destination |
put, broadcast, mail, fax, |
receive |
|
Receive |
Take or acquire from a source |
read, accept, peek, |
send |
|
Connect |
Associate subsequent activities with a resource |
disconnect |
||
Disconnect |
connect |
Appendix B - Standardized Parameters
The parameter list shown below is designed to be used in conjunction with the parameters listed with the verbs in the table at Appendix A.
Start by selecting a verb from the verb table. Next, determine which of the verb’s common parameters (listed in the same row of the table) you should support. If you need additional parameters, search the parameter table, shown below, and see if an existing parameter name covers the scenario you need. Using these two tables should cover a large percentage of scenarios. It is however expected that many commands will have unique parameters. In that case the command writer should add the command specific parameters as needed.
Parameter |
Type |
Definition |
Ubiquitous Parameters | ||
Confirm |
Boolean |
Ask user before operation is performed |
Description |
String |
Admins should be able to describe anything that they create to help them remember what it is and why it exists. Sometimes this can't be persisted but it can still be included in an Event |
PassThru |
Boolean |
For those Cmdlets that would direct output to somewhere other than stdout. |
Scope |
Keyword |
User, AllUsers, OS, Machine, Cluster, Domain, Local, Global, Script |
Verbose |
Boolean |
progress of operation is displayed on the progress stream |
Whatif |
Boolean |
Show what would occur if the command ran for real. (e.g. log activities that would take place) |
Activity Parameters | ||
CaseSensitive |
Boolean |
true = case sensitive, false = ignorecase |
Command |
String |
What command should be run |
Compatible |
String |
Identifies what semantics to be compatible with (used for backward compatiblity when changing semantics) |
Compress |
Boolean |
Whether to compress the data |
Compress |
Keyword |
How to compress the data |
Continuous |
Boolean |
Keep getting more information |
Create |
Boolean |
Determines whether to create a resource if one does not already exist |
Delete |
Boolean |
Delete resources when done |
Drain |
Boolean |
Wait for current activities to complete. |
Encrypt |
Boolean |
- |
Encrypt |
Keyword |
Type of encryption to use |
Erase |
Int32 |
Specifies the number of times a resource should be erased when it is deleted |
ErrorLevel |
int32 |
Level of problem to report |
ErrorLimit |
int32 |
Maximum number of errors that should occur before command is cancelled. |
Exclude |
String |
- |
Exclude |
Keyword |
- |
Fast |
Boolean |
- |
Filter |
string |
- |
Follow |
Boolean |
Track progress of an activity |
Force |
Boolean |
- |
Ignore |
Array of Keywords |
- |
Include |
String |
- |
Include |
Keyword |
- |
Incremental |
Boolean |
- |
Insert |
Boolean |
- |
Interactive |
Boolean |
- |
Interval |
hashtable of keyword/values |
e.g. -interval {resumescan<=15, retry<=3} |
Log |
Boolean |
progress of operation is displayed on the progress stream |
Migrate |
boolean |
- |
Notify |
Boolean |
Tell user about completion of an operation |
Notify |
Email Address |
Tell user about completion of an operation |
Overwrite |
Boolean |
- |
Prompt |
String |
- |
ReadOnly |
Boolean |
vs -Write |
Recurse |
Boolean |
- |
Repair |
Boolean or string |
- |
Retry |
int32 |
- |
Select |
Array of Keywords |
List of items to select |
SortBy |
String |
- |
Strict |
Boolean |
Consider any error a fatal error |
Temp |
Pathname |
Location of where to put temporary data |
Temp |
Boolean |
Changes are temporary |
TimeOut |
Int specifying Milliseconds |
- |
Trace |
Boolean |
Internal operations are displayed on the progress stream |
Truncate |
Boolean |
- |
Update |
Boolean |
Same as VERB |
Verify |
Boolean |
Perform a test to ensure that operation occurred |
Wait |
Int32 |
#of seconds cmd will wait for required resources to become available |
Wait |
Boolean |
Wait for user input before continuing |
Warning |
Boolean |
Controls whether optional warning messages are displayed |
Write |
Boolean |
vs -Readonly |
Date and Time Parameters | ||
Accessed |
Boolean |
Specifies which time -Before or -Since refers to. Incompatible with -Modified or -Created |
After |
DateTimeExpression |
- |
Before |
DateTimeExpression |
- |
Created |
Boolean |
Specifies which time -Before or -Since refers to. Incompatible with -Modified or -Accessed |
Modified |
Boolean |
Specifies which time -Before or -Since refers to. Incompatible with -Created or -Accessed |
TimeStamp |
Boolean |
Set or Get Timestamp |
Format Parameters | ||
As |
Keyword |
TCSV, Text, Script, XML, etc |
Ascending |
Boolean |
- |
Binary |
Boolean |
- |
Char |
int32 |
- |
Descending |
Boolean |
- |
Elapsed |
Boolean |
Show elapsed Time |
Encoding |
Keyword |
ASCII UTF8, Unicode, UTF7 |
Exact |
Boolean |
- |
Format |
String |
- |
NewLine |
Boolean |
- |
Shortname |
Boolean |
Use short names (e.g. 8.3 for filesystem) |
Width |
int32 |
- |
Wrap |
Boolean |
- |
Property Parameters | ||
Cache |
keyword |
- |
Count |
Int32 |
- |
Default |
Boolean |
- |
From |
ResourceName |
reference object to get information from |
Id |
??? |
- |
Input |
FileSpec |
- |
LineCount |
Int32 |
- |
LogName |
string |
- |
Location |
String |
- |
Name |
String |
- |
Output |
FileSpec |
- |
Owner |
?? |
- |
Parameter |
Hashtable |
Mechanism to pass attribute/values through a common command |
Password |
password |
- |
Priority |
Int32 |
- |
Property |
string |
Property Name |
Reason |
UserDescriptionString |
Why is this happening |
Regex |
Boolean |
Use regex instead of wildcarding for this command |
Statistic |
Keyword |
- |
Size |
int32 |
- |
Speed |
Pair of int32 |
Baud rate (input,output) |
State |
Array of Keywords |
Named state (e.g. KEYDOWN) |
Value |
object |
- |
Version |
VersionSpecifier |
- |
Quantity Parameters | ||
All |
Boolean |
- |
Allocation |
Int32 |
Number of items to allocate |
BlockCount |
int64 |
- |
Count |
int64 |
- |
Maximum |
Int32 |
Maximum number of items |
Minimum |
Int32 |
Minimum number of items |
Most |
Boolean |
Sensible subset of all |
Unique |
Boolean |
- |
Resource Parameters | ||
AssemblyName |
String |
- |
ApplicationName |
string |
- |
AttributeName |
string |
FileSystem attributes |
ClassName |
String |
e.g. type |
ClusterName |
String |
- |
ComputerName |
String |
- |
DirectoryName |
string |
- |
DomainName |
String |
Domain Name |
DriveName |
string |
Drive name e.g. C: |
EventName |
String |
Event Name (e.g. CRIMSON URI) |
FileName |
String |
- |
InterfaceName |
String |
Network Interface Name |
IpAddress |
IpAddress |
- |
JobName |
String |
- |
MacName |
MacAddress |
- |
ComputerName |
string |
Computer to operate on |
ParentID |
- |
- |
PortName |
string |
Int for networking but string for other types of port (eg Biztalk) |
PrinterName |
String |
- |
TID |
- |
Transaction ID |
TypeName |
string |
Type of resource to operate on |
URL |
string |
- |
UserName |
string |
- |
Security Parameters | ||
ACL |
- |
- |
CertFile |
FileName |
A file containing a Base64 or DER encoded x.509 certificate or a PKCS#12 file containing at-least one certificate and key. |
CertIssuerName |
String |
A string indicating the Issuer of a certificate, or a substring. |
CertRequestFileName |
String |
A file containing a Base64 or DER encoded PKCS #10 certificate request. |
CertSerialNumber |
String |
Serial number issued by cert authority |
CertStoreLocation |
String |
Location of certificate store. Typically a file path |
CertSubjectName |
String |
A string indicating the Issuer of a certificate, or a substring. |
CertUsage |
String |
A string representing the enhanced key usage or key usage. Can be represented as a bit bask, a bit, a oid or a string. |
CSPName |
String |
Name of the certificate service provider (CSP) |
CSPType |
Integer |
Type of CSP |
Group |
String |
A collection of principals |
KeyAlgorithm |
String |
Key generation algorithm |
KeyContainerName |
String |
Name of the key container |
KeyLength |
Int |
Key length in number of bits |
Operation |
String |
An action that can be performed on a protected object |
PrincipalName |
String |
Unique identifiable entity |
Privilege |
Array of Privs |
- |
Privilege |
string |
The ability to perform an operation |
Role |
String |
Group of operations |
SaveCred |
Boolean |
Use save credentials |
SID |
String |
Unique identifier representing a principal |
Trusted |
Boolean |
- |
TrustLevel |
Keywords (Internet, intranet, fulltrust etc) |
- |
Appendix C - Standardized Error Message Templates
The table below shows a list of Error Message Template strings. Elements in {}s are meant to be substituted but the other sigils are meant to be used to facilitate the easy visual parsing of the error messages. Thus the string “Insufficient Privilege to [{action}] ({resource}:{type})” would be used to generate the following error messages:Insufficient Privilege to [Delete] (C:\windows\system32\Burp.dll:FILE)Insufficient Privilege to [Modify] (HKLM:\software\microsoft\Burp:REGKEY)Insufficient Privilege to [STOP] (15:PROCESS)
Category ID |
Exit Code |
Template String |
Condition |
NoError |
0 |
No Error |
|
Close |
1 |
CloseError: ({targetname}:{type}) [{action}], ‘{reason}’ |
A close error occurred |
DeadlockDetected |
2 |
DeadlockDetected: ({targetname}:{type}) |
A deadlock was detected |
Device |
3 |
DeviceError: ({targetname}:{type}) [{action}], ‘{reason}’ |
A device error occurred |
InvalidArgument |
4 |
InvalidArgument: ({targetname}:{type}) [{action}], ‘{reason}’ |
Invalid Argument |
InvalidCategory |
5 |
Unrecognized error category {ErrorCategory}: ({resource}:{type}) [{action}], ‘{reason}’ |
Use of an unrecognized error category |
InvalidData |
6 |
InvalidData: ({targetname}:{type}) [{action}], '{reason}' |
The data is not valid for the operation |
InvalidOperation |
7 |
InvalidOperation: ({targetname}:{type}) [{action}] ‘{reason}’ |
The operation is not valid |
InvalidResult |
8 |
InvalidResult: ({targetname}:{type}) [{action}], ‘{reason}’ |
A result that falls outside of allows parameters. Underflow or Overflow |
InvalidType |
9 |
InvalidType: {type} ({targetname}) |
The type of the object is invalid for the target operation |
Metadata |
10 |
MetadataError: ({targetname}) ‘{reason}’ |
A Metadata error has occurred |
NotImplemented |
11 |
NotImplemented: [{action}] ({targetname}) |
The requested action is not implemented for the target |
NotInstalled |
12 |
NotInstalled: ({targetname}) |
Resource may be a cmdlet name or the underlying resource that a cmdlet may require. This is only used if it can be distinguished from “ResourceUnavailable” above and is known to not be installed. |
NotSpecified |
13 |
NotSpecified: ({Targetname}:{type}): [{action}], ‘{Reason}’ |
An unspecified error |
ObjectNotFound |
14 |
ObjectNotFound: ({targetname}:{type}) |
object can not be found (This can be a file, directory, system, resource, etc) |
Open |
15 |
OpenError: ({targetname}:{type}).: '{reason}' |
An open error has occurred |
OperationTimeout |
16 |
OperationTimeout: ({targetname}:{type}]) [{action}] |
The operation has timed out |
Parser |
17 |
ParseError ({targetname}:{type}) |
The parser error has occurred |
PermissionDenied |
18 |
PermissionDenied: [{action}] ({targetname}:{type}) |
Operation not permitted |
Read |
19 |
ReadError: ({targetname}:{type}) [{action}], ‘{reason}’ |
A read error has occurred |
ResourceBusy |
20 |
ResourceBusy: ({targetname}:{type}) |
The resource is busy |
ResourceExists |
21 |
ResourceExists: ({targetname}:{type}) |
The resource exists |
ResourceUnavailable |
22 |
ResourceUnavailable : ({targetname}:{type}) |
The resource is currently unavailable. A network resource that is temporarily not ready. |
Syntax |
23 |
SyntaxError: ({targetname}:{type}) |
A Syntax Error has occurred |
Write |
24 |
WriteError: ({targetname}:{type}) [{action}], ‘{reason}’ |
A Write Error has occurred |
Generic |
999 |
Provided for those errors that are not satisfied by the above categories |
Appendix D - Standardized Globbing
Globbing, which is similar to wildcard expansion, is typically used as an input filter. For example, a command may take a path as an input. Within that path globbing may be used to select multiple objects to operate on. A common case is in the file system where a user wants to see all files residing in the current folder (i.e. dir *). Commands should either support the full POSIX 1003.2, 3.13 specifications for globbing or the following simplified subset:
? |
A question-mark is a pattern that shall match any single character. |
* |
An asterisk is a pattern that shall match multiple characters |
[ |
The open bracket shall introduce a pattern bracket expression. |
Example:
PS> get-childitem
Directory: FileSystem::C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Oct 04 14:38 0 a
-a--- Oct 04 14:38 0 abc
-a--- Oct 04 14:38 0 b
-a--- Oct 04 14:38 0 c
-a--- Oct 04 14:38 0 d
-a--- Oct 04 14:38 0 def
-a--- Oct 04 14:38 0 ghi
-a--- Oct 04 14:38 0 XRAY
PS> get-childitem ?
Directory: FileSystem::C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Oct 04 14:38 0 a
-a--- Oct 04 14:38 0 b
-a--- Oct 04 14:38 0 c
-a--- Oct 04 14:38 0 d
PS> get-childitem [abc]
Directory: FileSystem::C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Oct 04 14:38 0 a
-a--- Oct 04 14:38 0 b
-a--- Oct 04 14:38 0 c
PS> get-childitem [ad]*
Directory: FileSystem::C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Oct 04 14:38 0 a
-a--- Oct 04 14:38 0 abc
-a--- Oct 04 14:38 0 d
-a--- Oct 04 14:38 0 def
PS> get-childitem [^abc]*
Directory: FileSystem::C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Oct 04 14:38 0 d
-a--- Oct 04 14:38 0 def
-a--- Oct 04 14:38 0 ghi
-a--- Oct 04 14:38 0 XRAY
PS> get-childitem [^a-m]*
Directory: FileSystem::C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Oct 04 14:38 0 XRAY
Appendix E - Standardized Data Example
Appendix F provides the Standardized Data Schema. Here we include a couple of C# classes and show the XML that it is serialized to as an aid to understand the Schema.
Note
This leverages many of the XSD types defined in https://www.w3.org/TR/xmlschema-2/ . This schema is in no way tied to .NET. Whenever you see something that looks like a .NET type name (e.g. contents of the <TYPEHIERARCHY>) it is merely a STRING “hint” to the user. This is made clear in Appendix F - CliXmlDataStream Data Schema. Win32 developers can use any string they want in this section, though they are cautioned to avoid using a string which would conflict with a .NET type name.
public class Zazu
{
public string p_String = "Zazu";
public int p_Int = 3;
}
public class Bar
{
public char p_Char = 'c';
public Guid p_Guid =
new Guid("8E3867A3-8586-11D1-B16A-00C0F0283628");
public byte p_UnsignedByte = 3;
public DateTime p_DateTime = new DateTime(2004,10,1);
public Decimal p_Decimal = new Decimal(44);
public Double p_Double = 3.1415;
public TimeSpan p_TimeSpan = new TimeSpan(1, 1, 1);
public float p_Float = 3.1415F;
public int p_Int = 3;
public long p_Long = 3;
public sbyte p_Sbyte = 3;
public short p_Short = 3;
public byte[] p_ByteArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public string p_String = "stringInstance";
public ushort p_UnsignedShort = 3;
public uint p_Uint = 3;
public ulong p_Ulong = 3;
public string p_Nil = null;
public Zazu p_Zazu = new Zazu();
}
<Objs Version="1.1" xmlns="https://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="RefId-0">
<TN RefId="RefId0">
<T>myCmdlets.Bar</T>
<T>System.Object</T>
</TN><Props>
<C N="p_Char">99</C>
<G N="p_Guid">8e3867a3-8586-11d1-b16a-00c0f0283628</G>
<By N="p_UnsignedByte">3</By>
<DT N="p_DateTime">2004-10-01T00:00:00</DT>
<D N="p_Decimal">44</D>
<Db N="p_Double">3.1415</Db>
<TS N="p_TimeSpan">PT1H1M1S</TS>
<Sg N="p_Float">3.1415</Sg>
<I32 N="p_Int">3</I32>
<I64 N="p_Long">3</I64>
<SB N="p_Sbyte">3</SB>
<I16 N="p_Short">3</I16>
<BA N="p_ByteArray">AAECAwQFBgcICQ==</BA>
<S N="p_String">stringInstance</S>
<U16 N="p_UnsignedShort">3</U16>
<U32 N="p_Uint">3</U32>
<U64 N="p_Ulong">3</U64>
<Nil N="p_Nil" />
<Obj N="p_Zazu" RefId="RefId-1">
<TN RefId="RefId-1">
<T>myCmdlets.Zazu</T>
<T>System.Object</T>
</TN><Props>
<S N="p_String">Zazu</S>
<I32 N="p_Int">3</I32>
</Props>
</Obj>
</Props>
</Obj>
</Objs>
Appendix F - CliXmlDataStream Data Schema
This leverages many of the XSD types defined in https://www.w3.org/TR/xmlschema-2/ . This schema is in no way tied to .NET.
Appendix G: Navigation Examples
Namespace Command |
Filesystem Command |
Set-location c:\test |
Cd c:\test |
Get-location |
pwd |
Get-childitem |
Dir |
Get-childitem d:\wango |
Dir d:\wango |
Get-content Burp.txt |
Type Burp.txt |
Get-content c:\test\Burp.txt |
Type c:\test\Burp.txt |
New-item bar -type directory |
Mkdir bar |
Remove-item tango.txt |
Del tango.txt |
Rename-item tango.txt zazu.txt |
Rename tango.txt zazu.txt |
Copy-item tango zazu |
Cp tango zazu |
Set-location hklm:\software\Microsoft |
|
Get-property WBEM |
|
Set-property WBEM PROP1 VALUE1 |
|
New-Property WBEM prop2 |
|
Remove-property wbem prop2 |
|
Set-location xml:\Burp.xml\root\element |
|
Get-content data |
Appendix H: Standardized Help Tags
Field Name |
Description |
alertSet |
These are special notes (like caution, warning, behavior while remoting, security issues, support info, etc) that need to be given to the user. For example, a note for the “format” cmdlet would say, “All your data will be lost by performing operation”. Support info might include the URLs of newsgroups where the user can look in for support on the help item. |
commandDescription |
This is a short description of the tool. Guidance is 12 words maximum,. |
commandErrors |
Describes the errors that the cmdlet throws. Warning and non-critical errors are also covered. Contains error tags. |
commandExamples |
One or more example(s) that show the usage of the tool/feature. Each example contains the codeExample, remarks, and results tags. |
commandParameters |
The parameters to the cmdlet. |
commandSyntax |
This describes how a tool/feature is used. Each of the parameters/switches of the tool are described in more detail under commandParameters. |
Configuration |
The required settings/configuration information/environment variables for the cmdlet |
Copyright |
A copyright message for the help content. This field is not displayed by default. |
Description |
Detailed description of the DocItem. This could be many pages long. |
inputTypes |
This describes the types of Input Object (DataObject) that the cmdlet expects as input. Contains inputType tags. |
name |
Name of the tool/feature.E.g.: dir, file, “Shell Internals”. |
noun |
The noun name of the command. This field is used for searching; it is not displayed by default. |
This section shows the layout of the XML for help. Optional elements and attributes are shown in italics; content is in boldface.
<commandHelp>
<commandDetails>
<name>sample-command</name>
<commandDescription>short description</commandDescription>
<synonyms>
<synonym>samp</synonym>
</synonyms>
<commandCopyright>(c) 2004 Microsoft</commandCopyright>
<verb>sample</verb>
<noun>command</noun>
<version>1.0</version>
<vendor>
<name>Microsoft Corporation</name>
<products>
<product>Microsoft Command Shell</product>
</products>
</vendor>
</commandDetails>
<description>
<para>
text
<parameterNameInline>parameter name</parameterNameInline>
<parameterValueInline>parameter value</parameterValueInline>
<commandInline>command example</commandInline>
<para>
<list class="ordered|unordered">
<listItem>
<para>text</para>
</listItem>
</list>
<definitionList>
<definitionListItem>
<term>term</term>
<definition>
<para>text</para>
</definition>
</definitionListItem>
</definitionList>
</description>
<commandSyntax>
<commandSyntaxItem>
<name>sample-command</name>
<commandSyntaxParameter>
<commandParameterName required="true">
-Parameter1
</commandParameterName>
<commandParameterValue required="true" variableLength="true"
type="literal">
ParamValue1
</commandParameterValue>
</commandSyntaxParameter>
<commandSyntaxParameter>
<commandParameterName required="true">
-Parameter2
</commandParameterName>
<commandParameterValueGroup required="true">
<commandParameterValue>
ParamValue21
</commandParameterValue>
<commandParameterValue>
ParamValue22
</commandParameterValue>
</commandParameterValueGroup>
</commandSyntaxParameter>
</commandSyntaxItem>
</commandSyntax>
<commandParameters>
<commandParameter required="true" variableLength="true"
globbing="true" pipelineInput="true"
position="0">
<name>-Parameter2</name>
<commandParameterValue required="true" variableLength="true"
type="literal">
ParamValue2
</commandParameterValue>
<type>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</type>
<description>
<para>text</para>
</description>
<defaultValue>default Value</defaultValue>
<validation>
<minCount>1</minCount>
<maxCount>2</maxCount>
<minLength>1</minLength>
<maxLength>10</maxLength>
<minRange>5</minRange>
<maxRange>10</maxRange>
<commandParameterValueGroup required="true">
<commandParameterValue>
ParamValue21
</commandParameterValue>
<commandParameterValue>
ParamValue22
</commandParameterValue>
</commandParameterValueGroup>
</validation>
</commandParameter>
</commandParameters>
<inputTypes>
<inputType>
<type>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</type>
<description>
<para>text</para>
</description>
</inputType>
</inputTypes>
<returnTypes>
<returnType>
<type>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</type>
<description>
<para>text</para>
</description>
</returnType>
</returnTypes>
<terminatingCommandErrors>
<terminatingCommandError>
<type>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</type>
<description>
<para>text</para>
</description>
<errorId>error-id</errorId>
<suggestedAction>text</suggestedAction>
<targetObjectType>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</targetObjectType>
<category>category</category>
</terminatingCommandError>
</terminatingCommandErrors>
<nonTerminatingCommandErrors>
<nonTerminatingCommandError>
<type>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</type>
<description>
<para>text</para>
</description>
<errorId>error-id</errorId>
<suggestedAction>text</suggestedAction>
<targetObjectType>
<name>Typename</name>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</targetObjectType>
<category>category</category>
</nonTerminatingCommandError>
</nonTerminatingCommandErrors>
<alertSet class="note|configuration">
<title>title</title>
<alert>
<para>text</para>
</alert>
</alertSet>
<commandExamples>
<commandExample>
<commandLines>
<commandLine>
<commandText>$> </commandText>
<commandText input="true" newline="true">
sample-command
</commandText>
<commandText>output</commandText>
</commandLine>
</commandLines>
<description>
<para>text</para>
</description>
</commandExample>
</commandExamples>
<relatedLinks type="seeAlso">
<navigationLink>
<linkText>text</linkText>
<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>
</navigationLink>
</relatedLinks>
</commandHelp>
Appendix I: Win32 Code to Write Output
void
MyWriteConsole(
HANDLE fp,
LPWSTR lpBuffer,
DWORD cchBuffer
)
{ if(!lpBuffer || !cchBuffer)
{ assert(false);
return;
}
//
// Jump through hoops for output because:
//
// 1. printf() family chokes on international output (stops
// printing when it hits an unrecognized character)
// 2. WriteConsole() works great on international output but
// fails if the handle has been redirected (i.e., when the
// output is piped to a file)
// 3. WriteFile() works great when output is piped to a file
// but only knows about bytes, so Unicode characters are
// printed as two Ansi characters.
if (FILE_TYPE_CHAR == FileType(fp))
{ WriteConsole(fp, lpBuffer, cchBuffer, &cchBuffer, NULL);
}
else if (g_fUnicodeOutput)
{ //Buffer bounds are passed correctly.
WriteFile(fp, lpBuffer, cchBuffer*sizeof(WCHAR), &cchBuffer, NULL);
}
else
{ int nSizeAnsiBuffer = WideCharToMultiByte(CP_OEMCP,
0,
lpBuffer,
cchBuffer,
NULL,
0,
NULL,
NULL);
if(nSizeAnsiBuffer > 0)
{
LPSTR lpAnsiBuffer = (LPSTR) LocalAlloc(LPTR, nSizeAnsiBuffer);
if (lpAnsiBuffer != NULL)
{
cchBuffer = WideCharToMultiByte(CP_OEMCP,
0,
lpBuffer,
cchBuffer,
lpAnsiBuffer,
nSizeAnsiBuffer,
NULL,
NULL);
if (cchBuffer != 0)
{
WriteFile(fp, lpAnsiBuffer, nSizeAnsiBuffer, &cchBuffer, NULL);
}
LocalFree(lpAnsiBuffer);
}
}
}
}
Appendix J - Using Windows PowerShell to implement the Microsoft Command Line Standard
This document defines a set of guidelines to provide a consistent, composable command line user experience. Developers can implement these guidelines however they chose, however if they implement Windows PowerShell Cmdlets, they will get much of this for free. Specifically:
Command Names |
Windows PowerShell Cmdlets ensure proper verb-noun naming. |
Consistent Syntax |
Windows PowerShell handles the parsing of the command line entirely. Your Cmdlet class specifies a set of metadata which then drives the Windows PowerShell parser. |
Input |
Windows PowerShell accepts and encodes input (either directly or through a set of utility functions) from a wide range of formats including XML, TCSV, ADO, PropertyBags, etc. This input is used to populate your Cmdlets public properties before calling your Cmdlet’s ProcessRecord() method. |
Parameters |
Windows PowerShell implements for -?, -Help, -Version, -Verbose and -Debug. Your command will be responsible for supplying the data for these functions either through well defined data elements (e.g. help files) or by calling well defined APIs (e.g. WriteVerbose() and WriteDebug()). |
Targeting |
Windows PowerShell provides an extensible globbing model which allows development of type-specific globbers which can be used by any command. |
Output Formatting |
Cmdlets provide their results as a stream of .NET objects to Windows PowerShell which then handles formatting and outputting them. Windows PowerShell will format output to a wide (and growing) range of output types and formats including LIST, TABLE, Wide, XML, HTML, ASCII, UTF7, UTF8, UTF32, UNICODE, and BigEndianUnicode. Windows PowerShell will respect the environmental variable CliXmlStreams and render all streams in XML using CliXmlDataStream Schema. When outputting to CliXml, Windows PowerShell provides a declarative mechanism to map your .NET objects into CliXml but has a default serialization policy if no declarations are provided (It serializes the public known-type [those defined in Appendix F - Standardized Data Schema] properties of your object graph to a depth of 2 where unknown types are transformed into property bags which add a level to the object graph. Properties beyond the depth 2 are rendered to strings.) |
Errors |
Windows PowerShell ensures that all errors, verbose and debug statements are written to STDERR and will properly set the exit code of the process. Windows PowerShell provides a set of APIs which make it easy to support and output Standardized Error Messages. Windows PowerShell will provide the user the syntax of the command if they specify a syntactically invalid command. |
Appendix K - Error Record Schema
The following schema describes the error information that must be emitted by an application. It is a proper subset of the Windows PowerShell ErrorRecord.
<xsd:schema targetNamespace=https://schemas.microsoft.com/msh/2004/04
xmlns:msh=https://schemas.microsoft.com/msh/2004/04
elementFormDefault="qualified"
xmlns:xsd="https://www.w3.org/2001/XMLSchema">
<!-- ErrorRecord is the toplevel element -->
<xsd:element name="ErrorRecord" type="msh:ErrorRecord">
<!-- Definition of complex type ErrorRecord -->
<xsd:complexType name="ErrorRecord">
<xsd:complexType name="Exception" minOccurs="0" maxOccurs="0" />
<xsd:element name="Message" use="optional" type="xsd;string" />
</xsd:complexType>
<xsd:element name="TargetObject" minOccurs="0" maxOccurs="1" type="xsd:string" />
<!-- Define CategoryInfo -->
<xsd:complexType name="CategoryInfo">
<xsd:attribute name="Category" use="optional" type="xsd:string" />
<xsd:attribute name="Activity" use="optional" type="xsd:string" />
<xsd:attribute name="Reason" use="optional" type="xsd:string" />
<xsd:attribute name="TargetName" use="optional" type="xsd:string" />
<xsd:attribute name="TargetType" use="optional" type="xsd:string" />
</xsd:complexType>
<xsd:element name="FullyQualifiedErrorId" minOccurs="0" maxOccurs="1" type="xsd:string" />
<!-- Define ErrorDetails -->
<xsd:complexType name="ErrorDetails">
<xsd:attribute name="Message" use="required" type="xsd:string" />
<xsd:attribute name="RecommendAction" use="optional" type="xsd:string" />
</xsd:complexType>
<!--Define InvocationInfo -->
<xsd:complexType name="InvocationInfo">
<xsd:complexType name="MyCommand">
<xsd:attribute name="Name" use="mandatory" type="xsd:string" />
<xsd:attribute name="Vendor" use="mandatory" type="xsd:string" />
<xsd:attribute name="Version" use="mandatory" type="xsd:string" />
<xsd:attribute name="Product" use="mandatory" type="xsd:string" />
</xsd:complexType>
<xsd:attribute name="InvocationName" use="mandatory" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
Appendix L - Enhanced Interoperability Guidance
There are three levels of interoperability: UNIX, Enhanced, and Optimal. UNIX interoperability refers to the traditional “write text to STDOUT and exit with 0 if successful” model. Summary List of Guidance documents the guidance to achieve Optimal interoperability. This section contains guidelines to achieve Enhanced interoperability. Enhanced interoperability provides developers with a small set of concrete steps that they can do to improve existing commands on the way to achieving Optimal interoperability.
Consistent Syntax
Required:
- Commands must use the “-“ character for parameter delimitation; the “:” character or whitespace to separate parameters and their arguments and the “,” character to separate multiple values.
Parameters
Required:
Commands must support -?, -Help, -Version, -Verbose, and -Debug for all commands.
Parameter names must be case-insensitive.
Output Formatting
Required:
Output must be written using the logic illustrated in Appendix I: Win32 code to write output to properly address globalization requirements.
Commands must support the -OutputFormat parameter to allow users to specify their desired format and the -OutputPreamble to configure schema enhanced data streams
Commands must use of the value of the environmental variable CliDataStreamSchema when -OutputFormat is not specified.
Commands must support at least one format of schema-enhanced dataStreams (TCSV or CliXml).
Exit, Errors, and Others
Required:
Error messages (as well as VERBOSE and DEBUG messages) must be written to stderr.
Commands must terminate with an exit coding indicating success (0) or failure (non-zero).
Appendix M - Typed-CSV (TCSV) Data Format
This appendix describes the Typed-CSV (Comma Separated Values) serialization format. This format will be used when importing and exporting data (import-CSV and export-CSV command) and when data needs to be serialized across process boundaries. While XML is generally considered a more modern solution for data exchange, there are bandwidth critical situations where CSV is a better alternative because of the lower overhead. This format serves as a low overhead data exchange format. Using CSV will be possible when the data is a homogenous collection of objects and the object properties are of simple types.
The CSV format is commonly used but its definition remains fuzzy. This appendix builds upon the common CSV practices and defines the precise formatting rules for TCSV.
The TCSV Data stream format
Each record is one line ...but
A record separator may consist of a line feed (ASCII/LF=0x0A), or a carriage return and line feed pair (ASCII/CRLF=0x0D 0x0A).
...but: fields may contain embedded line-breaks so a record may span more than one line.
Fields are separated with commas.
Example John,Doe,120 any st.,"Anytown, WW",08123
Leading and trailing space-characters adjacent to comma field separators are ignored.
So John , Doe ,... resolves to "John" and "Doe", etc. Space characters can be spaces, or tabs.
Fields with embedded commas must be delimited with double-quote characters.
In the above example. "Anytown, WW" had to be delimited in double quotes because it had an embedded comma.
Fields that contain double quote characters must be surrounded by double-quotes, and the embedded double-quotes must each be represented by a pair of consecutive double quotes.
So, John "Da Man" Doe would convert to "John ""Da Man""",Doe, 120 any st.,...
A field that contains embedded line-breaks must be surrounded by double-quotes
So:
Field 1: Conference room 1
Field 2:
John,
Please bring the M. Mathers file for review
-J.L.
Field 3: 10/18/2002
...
would convert to:
Conference room 1, "John,
Please bring the M. Mathers file for review
-J.L.
",10/18/2002,...
Note that this is a single TCSV record, even though it takes up more than one line in the TCSV data stream . This works because the line breaks are embedded inside the double quotes of the field.
Fields with leading or trailing spaces must be delimited with double-quote characters.
So to preserve the leading and trailing spaces around the last name above: John ," Doe ",...
Fields may always be delimited with double quotes.
The delimiters will always be discarded.
The first record in a TCSV data stream must be a header record containing column (field) names
The header row is encoded just like any other CSV record in accordance with the rules above. A header row for the multi-line example above, might be:
Location, Notes, "Start Date", ...
The second record in a TCSV data stream must be a type-definition record containing datatypes for the columns defined in the first record.
The type-defintion row is encoded just like any other CSV record in accordance with the rules above. The typesnames must be from the list of types defined in Appendix F - CliXmlDataStream Data Schema.
Empty fields will be interpreted as missing values.
Appendix N - Argument Parsing Pseudo code
The code below serves as pseudo code for an implementation for argument parsing. It is written in Windows PowerShell to ensure that it works, to use constructs that have clearly defined semantics, and to express complex logic in a pithy way.
#################################################################
#
# Utility routine to convert an argument to the target type.
# This routine also handles array conversions...
#
function convert-argument ([string] $argument, [type] $type)
{
#
# Arguments should be split into arrays on comma boundries
# Split always produces an array so a scalar argument ends
# up as an array anyway...
# Note: quoting of commas is not shown here. A literal comma
# would have to be quoted with a backquote...
#
$result = $argument.split(",")
#
# If the target type is an array, simply convert the string
# array into the target array
#
if ($type.IsArray)
{
$result -as $type
}
else
{
if ($result.length -gt 1) {
write-error -term "can't assign an array argument to a scalar"
}
$result[0] -as $type
}
}
#################################################################
#
# Parse an array of arguments in a manner consistent with msh
#
# $arglist is an array of strings to be parsed
# $signature is a hash table describing the signature for this command
# Entries take the form of
#name = [type]
# The result of the parse will be to return a hash table
# mapping actual parameters to their values, including the type conversions
#
function parse ($signature, $arglist)
{
$i = 0
$argsLength = $arglist.length
# The $result hash table holding the parsed results
# Any unclaimed arguments will be in the __rest member.
$result = @{};
# an array holding the unclaimed argument values...
$rest = @()
:firstloop
while ($i -lt $argsLength)
{
switch -regex ($arglist[$i])
{
#
# Process arguments of the form
# -foo: 123
# in this form, arguments must be present in the signature array
# and always take an argument
#
'^-([a-zA-Z][a-zA-Z0-9]*):$' {
$argName = $matches[1]
$type = $signature[$argName]
if (! $type)
{
write-error -term "-$argName is not a valid argument"
}
$i += 1
if ($i -ge $argsLength)
{
write-error -term "missing argument to -$argName"
}
$result[$argName] = convert-argument $arglist[$i] $type
break;
}
#
# Process arguments of the form
# -foo:123
# That is, no space between the colon and the argument
# In this case, argument is part of this array element
#
'^-([a-zA-Z][a-zA-Z0-9]*):(.+)$' {
$argName = $matches[1]
$argument = $matches[2]
$type = $signature[$argName]
if (! $type)
{
write-error -term "-$argName is not a valid argument"
}
$result[$argName] = convert-argument $argument $type
break;
}
#
# Process arguments of the form
# -foo 123
# or
#-foo
# in this form, if the argument is in the signature,
# and it's type is boolean, no arg is required or permitted.
# If it's not boolean, then an argument must be provided
# If the parameter is not in the signature set, then it's
# treated as a positional
# argument.
#
'^-([a-zA-z][a-zA-Z0-9]*)$' {
$argName = $matches[1]
$type = $signature[$argName]
# if it's not explicitly a parameter, it's an argument
if (! $type)
{
$rest += $_
}
elseif ($type -eq [bool])
{
$result[$argName] = [bool]1;
}
else
{
$i += 1
if ($i -ge $argsLength)
{
write-error -term "missing argument to -$argName"
}
$result[$argName] = convert-argument $arglist[$i] $type
}
break;
}
#
# Handle the -- end-of-options indicator
# everything after this is simply an argument
#
'^--$' {
$i += 1;
break firstLoop;
}
#
# Things that don't start with a - are just arguments
#
default {
$rest += $_
}
} # end switch
$i += 1
}
#
# Now process any remaining arguments and add them to __rest
:secondLoop
while ($i -lt $argsLength)
{
$rest += $arglist[$i]
$i += 1
}
$result["__rest"] = $rest
$result
}
# end parse
#
#################################################################
#################################################################
#
# Define an example signature
#
$sig = @{
foo = [int]
bar = [bool]
baz = [string]
buz = [double]
biz = [double[]]
}
#
# And a test function...
#
function testparse {
parse $sig $args
}
trap {
write-host ("parse error: " + $_.message)
continue
}
#
# examples using parse
#
"`nExample 1"
testparse -foo: 2 -zork -bar -buz 3.14 -baz: "Hello world"
"`nExample 2 using --"
testparse -foo: 2 -zork -bar -buz 3.14 -- -baz: "Hello world"
"`nExample 3 - colon after boolean argument"
testparse -foo: 2 -zork -bar: false -buz 3.14 -baz: "Hello world"
"`nExample 4"
testparse -foo: 2 -zork -bar -buz 3.14 -baz: "Hello world" -- `
-some -nonargument -flags
"`nExample 5 - doesn't use testparse because msh parsing will split at the :"
parse $sig "-foo:2","-zork","-bar","-buz",3.14,"-baz:","Hello world","--", `
"-some","-nonargument","flags"
"`nExample 6"
testparse -foo: 2 -zork -bar -buz 3.14 -baz: "Hello world" -biz "1,2,3"
"`nExample 7 - assigning a scalar to an array"
testparse -foo: 2 -zork -bar -buz 3.14 -baz: "Hello world" -biz 1
"`nExample 8 - assigning an array to a scalar - this will fail..."
testparse -foo: 2 -zork -bar -buz 3.14 -baz: "Hello world,a,b"