One ongoing annoyance I have with commandline tools is that getting a single new tool requires learning a new vocabulary for using that tool. Sure, there are putative standards and if you've dealt with UNIX/Linux systems before you can trust that certain ported tools will use particular conventions, but that doesn't help with the nonstandard ones.
I'm of course eventually going to use this as an opportunity to mention why I really like MSH, but today I just want to talk about the current console problems. Talking about MSH will come later because the effect of MSH will be complex. If you're wanting a word bite on it right now: in theory MSH can completely resolve this problem; in practice it won't guarantee everything but it will probably shrink the problem by two orders of magnitude.
To illustrate how bad the conventions and names nightmare can be, let's look at integrating a set of new tools into your standard console toolbox. It's only by looking at commands taken together that the annoyances become apparent.
Let's say tools you're adding tools dealing with 6 important object types: services, xml structures, users, files, permission structures, and printers. Let's also say that there are 5 different operations done on each object by the various tools - in other words, you have 30 different console utilities. (This is a little extreme; some tools provide multi-role use allowing you to specify a parameter that switches modality, so it COULD be as little as 6 tools - but not likely). Let's also say these operations are the same 5 for all object types: listing, setting/saving, copying, moving, and deleting.
At this point, we already have some complications. You need to "know" the names to invoke the tools or even find them. Do they use the same name form? Is it a bare object name? A bare operation name like "duplicate"? Are they abbreviated? How do they concatenate the operation and the object name, if they do at all? I've seen cp, copy, cpy, dup, duplicate, and even newfrom as synonyms for copy. If you don't have all of the tools for an object set from the same source - certainly possible - it can be even stranger. For example, I have 4 standalone commandline cd-burning tools that I know of in my \bin folder: CreateCD, cdburn, oscdimg, and hd2iso. I say that I know of because that bin folder has many files and some unusual names; I originally overlooked hd2iso for example. You may get lucky and have some standard names if tools come in a set; then again, you may not. If you're working with services, you've used the "net" command for start, stop, pause, and resume on a service; but disabling or enabling takes switching over to sc.exe with a completely distinct syntax. The worst case scenario is that you have to "know" 36 different words: 6 object types and 5 distinct operation names for each of the objects. In practice, it would be less since you would have some contextual clues that help you see a pattern. In fact, if they're distinct tools, you could even try renaming them to fit a pattern, something I've done for convenience before. (If you try this, be warned there are LOTS of possible nasty side effects).
Setting aside command name confusion, each of these operations/commands/tools may have very distinct specialty parameters or options you may need to use. Let's take 5 things that all of these commands COULD benefit from: verbosity, help, error handling, a target computer, and an "if" mode that lets you see the effect of changes without actually committing them. If you're familiar with some tools from different environments, you know how these can vary. Again, the VERY worst case possible for intuitive use is that each tool is from a different person informed by a very different computing culture. Spelling out the obvious, we have as many as 150 distinct parameter names, and we haven't touched the behavior. Does invoking help return information to stdout or stderr? Are parameters case-sensitive? Can you provide partial parameter names? What happens if you provide a bad parameter? Does the tool stop or does it run along doing what it did before and ignore extra parameters? If it stops, does it set the errorlevel? And does it echo help info and scroll your error off the screen? (Oops, that's not a naming issue, just an annoyance). What's the character used for parameter flagging, '-' or '/'? Are values separated from parameter names by a space, a colon, an equal sign, nothing, or something else? And how do we correlate all of these with no guidance?
Chances are it isn't quite that bad, of course, since naming patterns are possibly identical in toolsets. In that case, you may have only about 6 distinct sets of parameters, and if every single one of those object-centered toolsets is complete (provides all operations you need) then you have about 30 names in 6 different naming patterns and about 30 distinct parameter names at most. It would be difficult to get the theoretical worst-case of 150 distinct parameter names (and unlikely for there to be even 30 in the restricted case); there are only so many synonyms for the word "help" in English. There are definitely 2-3 synonyms in use for most common parameters, however; and computers being literal, issues such as partial names, case-sensitivity, and parameter flag characters mean that there are likely to be multiple distinct "correct" names and therefore opportunities for accidental misuse. There is another twist as well: homographic parameters, ones that are spelled alike but have different meanings. For example, taskkill uses /F for "force" and xcopy uses /F for "fullname".
At this point, I'm glad this is a blog and not an article; I don't have to show a way to fix this right now in 3 easy steps. Later on I'll talk about some sources of this problem (there are lots and I don't know most of them) and what changes in the MSH context (a lot, although it can't directly do much about ugly legacy tools).
One of the beta testers in the MSH groups recently mentioned that the verb-noun form for MSH aliases looks rather alien to programmers; it just doesn't feel right using new-object instead of New-Object, for example.
Those of us who have been in the beta for a while are very used to the concept of aliasing for familiarity. This is an easy one to reskin:
MSH> get-command | foreach-object { set-alias $($_.Verb + $_.Noun) $_.Name}
And suddenly every MSH cmdlet has a "standard" name without the hyphenation.
[Listening to: Hey Hey What Can I Do / Hootie - Encomium - A Tribute to Led Zeppelin (03:25)]
... that can make the biggest difference.
Ever since I started working with console-based WSH scripts, I found the tendency to break input pipes if not launching explicitly with cscript to be a source of frustration and actual damage.
A few weeks ago, I started using "shadow scripts": I would generate a CMD or BAT file with the same base name as a WSF, in the same folder, and give it the one line:
@cscript "%~dpn0.wsf" %*
Although it was a little annoying to do at first, I found that I was suddenly writing more and more console scripts due to how simple use was. It makes calling and piping ten times easier.
[Listening to: Mozart - Fur Elise (03:34)]
While looking for a way to handle patch management mini-tasks, I ran across the following response by a Microsoft employee to a request for the schema for mssecure.xml (in context, the softie did not sound happy about having to give this kind of answer):
Microsoft doesn't publish the schema for the MSSECURE.XML file. We reserve the right to modify, change and update the schema as necessary to enhance products that rely on and use the MSSECURE.XML file.
That's not precisely true. Microsoft does publish a schema, an implicit one. What people tend to forget is that any well-formed XML file conforms to a schema. It may not be a formal one or even an appropriate one, but a schema can be inferred from that XML file instance.
Of course, no one wants to spend hours trying to determine a schema from a 1.7 MiB file. If you get Microsoft's own xsdinfer tool, though, you can automatically parse the schema in seconds.
I proceeded to do that with the latest (2003-10-03) mssecure.xml and I have made the inferred mssecure.xsd file available as a zipped download.
Note that this is incredibly easy to do. I simply ran
infer mssecure.xml -o mssecure
and had mssecure_1.xsd ready in seconds. The schema is very clean considering the size of mssecure.xml; it reduces to 11.8 KiB and compresses to 1.7 in the download.
[Listening to: We Have Explosive - The Future Sound of London - We Have Explosive (03:26)]
I've been going through Visual Basic .NET 2003 Resource Kit this morning, looking for goodies I can reuse elsewhere. One of the "metrics" I use is how good console tool support is.
Strictly speaking, this is not a VB issue, it is a .NET issue, and I'm finding myself wandering off to think about the whole issue of console tool support as a concept in Windows systems. The real underlying problem is not one of what classes are available here and there for console tools. The problem is that programmers don't usually realize that a console application is to an administrator what a class is to a programmer.
A CLI application is really a component, and to be the best at what it does, it needs to be self-contained, use common switches, and understand working with stream for input, output, and error. It needs to be self-describing as well, so that help is just moments away.
I'm not quite sure what the "best" answer is, but there is no doubt that a core library which allows simple, single-step generation of help text and internal primitives for scripts and for compiled applications could make an immense difference to the growth of well-behaved, admin-friendly building block applications.