Monday, August 3, 2015

PowerShell - Microsoft's Trident: Part 2, Cmdlets

The Second Point on the PowerShell Trident

In a previous post I began to look at the three aspects of PowerShell that make it so powerful. In that first article I examined the shell itself, and how it can be used to do some really cool things. Now for the second point…

Cmdlets (/kəˈmandlits/)

Cmdlets are wonderful things. As I stated in that last article, you can run just about any command in the PowerShell shell. But why would you? Between .NET (see that previous article) and the three-thousand-or-so cmdlets in PowerShell 3 and later, anything you need to do from the command line is taken care of.
Yes, initially there will be a bit of a learning curve, but it’s not nearly so bad as you might think, and the advantages far outweigh the inconvenience of learning something new. Besides, as a mentor of mine once said, “The day you stop learning is the day you start dying.” So let’s learn what makes cmdlets so cool.

1. They’re consistent.

If you’ve used any command line environment in the past—CP/M, UNIX, DOS—one source of endless frustration is the lack of consistency among all those commands. “Can you use a space here? Are parameters prefixed with a slash, a dash, two dashes, or not at all? Are they case sensitive?” The very fact that one must even ask such questions makes learning to use the command line difficult and contributes to it’s bad reputation.
But really, it’s foolish to expect anything else. Each of those commands was written by different people at different times to solve different problems. Their authors each had his own experiences and way of thinking that affected how he would address his particular need. It’s only natural that those commands bear little resemblance to one another.
But then came the GUI. When Apple introduced the Lisa in the early eighties it also published a style guide so that developers could write programs that correspond to the system’s look and feel. Microsoft did the same when Windows was released some years later. Building on that experience, Microsoft has provided some recommendations for developers of new cmdlets so that users don’t have to face the arduous task of learning a new set of commands from scratch. In theory, once you learn how to use one cmdlet you can apply that knowledge to any cmdlet. In practice, it works really well.

2. They’re well-documented.

Referring to those operating systems previously mentioned: help in CP/M was non-existent; in DOS it was terse and sometimes cryptic; and while often useful and informative in UNIX the man pages for commands are as diverse and inconsistent as the commands themselves. When a user has to toil by the sweat of his brow to unearth a little information, it’s little wonder that he would run the other way rather than learn how a command works.
PowerShell, though, is actually helpful. The Get-Help cmdlet provides different levels of verbosity, from printing out basic syntax to highlighting every detail of each argument that a cmdlet will accept. It can even display working examples of how a cmdlet is used, which fits my learning style perfectly. You can also search through the help using the standard shell wildcard characters * and ?.
And it’s thorough. Not only can you find information on cmdlets, but concepts are documented as well. Try Get-Help about_arithmetic_operators to find out how PowerShell does math, or Get-Help about_if to review how PowerShell makes decisions. If you need to know something about PowerShell, like Prego spaghetti sauce, “It’s in there.”

3. They return objects.

One of the things that makes it difficult to use command line tools is that they go about their business, perhaps print something on the screen, and leave. This is fine if you happen to be hanging about to read the output, but makes things tough if you want to automate some task in a script. The problem is one of parsing.
Let’s say that I want to fetch a computer’s IP address from DNS and use that address in some other process. I can use:
nslookup www.centriq.com
Since I can see the result on screen, I can parse the output, find the relevant data, and do what I want to with it. Humans are good at this sort of thing; computers, not so much. Let’s try to fetch just the IP address in cmd.exe with some fancier command-fu:
set host=www.centriq.com
for /f "usebackq tokens=2" %%i in (`nslookup %host%`) do set ipaddr=%%i
Now I have a variable called ipaddr that contains the IPv4 address of host, right? Well, maybe. The problem is that nslookup changes its output depending on the information in the DNS record it queries. This command expects the data of interest to be on the last line of output, which will work much of the time, but not always.
Compare that to the following:
$host = 'www.centriq.com'
$ipaddr = resolve-dnsname $host | ? ip4address | select -expand ip4address
If an A record for host exists, the ipaddr variable will always contain an IPv4 address. No doubt about it, and no parsing necessary. The object that PowerShell creates from the Resolve-DNSName cmdlet will have an IP address property that we can directly query and save in a variable.
In fact, all of those objects have useful properties and methods that we can use to customize the output of a cmdlet or even change the state of a computer. These objects can start services, kill processes, change passwords, and so on. They are infinitely more useful than a few lines of text output upon a computer screen.

If you’ve ever found the command line infuriating don’t let that stop you from learning how to get what you want from PowerShell. Its cmdlets were designed to address the very frustrations you’ve had with other shells. While learning this new system will require an investment of time and effort, the dividends are definitely worth it.
Stay tuned for part three of this series. Be seeing you.

No comments:

Post a Comment