# 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.

### Introduction

In order to provide a consistent, composable user experience, across a wide range of commands, this document provides guidance on:

1. Consistent verb and parameter naming conventions.

2. Consistent command syntax

3. Common behaviors.

4. Consistent error messages and exit codes.

5. 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:

1. Common Object Verbs Some of these will be used with almost every noun. For example, many nouns will support the “New” and “Remove” verbs.

2. Data Verbs These are used with data intensive operations and include “Compare” and “Merge”.

3. Lifecycle Verbs These are envisioned to be used with activities. The lifecycle verbs include “Start”, “Stop” and “Resume”.

4. Diagnostic Verbs As the name implies, these are for diagnostic purposes. The set includes “Measure”, “Test” and “Debug”.

5. 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: 1. 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”.) 2. Specify a date time related parameter (e.g. -Modified, -Before -Since) 3. Request a format (e.g. -Encoding, -Width, -Wrap) 4. Specify a common property or resource (e.g. -Count, -Description, -Name) 5. 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. 1. 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”. 2. 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. 3. 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 http://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="http://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 http://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>$&gt; </commandText>
<commandText input="true" newline="true">
sample-command
</commandText>
<commandText>output</commandText>
</commandLine>
</commandLines>
<description>
<para>text</para>
</description>
</commandExample>
</commandExamples>

<uri href="href" uri="uri" ref="ref">
<summary>URI summary</summary>
</uri>

</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=http://schemas.microsoft.com/msh/2004/04
xmlns:msh=http://schemas.microsoft.com/msh/2004/04
elementFormDefault="qualified"
xmlns:xsd="http://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;
}

#
#
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"

`
Show: