More Power with PowerShell - Class Review

This is the third year that USENIX has offered PowerShell training at LISA, and the first I've been able to get into the class to take it. I'm so glad I could finally do it, because even though I use PowerShell almost every day to administer my vSphere clusters (through the excellent PowerCLI extension by VMware), I don't feel like I have a really solid grasp of the language as a whole. 

As it turns out, I'm not alone. There are tens of thousands of "cmdlets" (pronounced "commandlettes") throughout PowerShell, and as instructor Steven Murawski says, "no one knows all of PowerShell". It's a good thing that there are a lot of utilities to help you figure out what you want to use and how to use it! 

Steven started us out with the "Big Four": 

  • Get-Command

This cmdlet will allow you to list all of the available commands - or just a subset, based on a regex of the command name, what type of command it is, and what piece of software provides it. 

  • Get-Help

This is the equivalent of the 'man' command in UNIX. Get-Help cmdlet-name will give you an explanation of the cmdlet and what it does. You can also get extended documentation, examples, or even launch a web browser to the online documentation (with the very cool -online flag that I didn't know about until today!) 

  • Get-Member

This is one of my favorite commands. If you're used to slinging around command lines in Linux or UNIX, you're used to pretty much everything being a text string, and if you want information out of a particular field, you need to make sure to get the right line and know the right field number. PowerShell, on the other hand, throws around objects, and because objects are in many ways self-documenting regarding the data that they contain, you can have your command make decisions based on that - pulling out specific fields or doing math on the fly, all by using the data's actual field name instead of something like $8.

A lot of time, though, you don't know (or can't remember) what values a particular object has. That's when the Get-Member command comes to the rescue. Here's an example: 

Suppose I'm dealing with a VM. I'm able to select the vm pretty easily: 

[vSphere PowerCLI] V:\powergu.211\vSphere PowerCLI> get-vm -name xevious

Name                 PowerState Num CPUs Memory (MB)
----                 ---------- -------- -----------
xevious              PoweredOn  1        3072


But according to that, it only has a few values. I know there's more. To see what it's got, I can just pipe that command into Get-Member: 

[vSphere PowerCLI] V:\powergu.211\vSphere PowerCLI> get-vm -name xevious | Get-Member

   TypeName: VMware.VimAutomation.Client20.VirtualMachineImpl
Name                MemberType Definition ----                ---------- ---------- Equals              Method     bool Equals(System.Object obj) GetHashCode         Method     int GetHashCode() GetType             Method     type GetType() ToString            Method     string ToString() CDDrives            Property   VMware.VimAutomation.Types.CDDrive CustomFields        Property   System.Collections.Generic.IDictio DatastoreIdList     Property   System.String[] DatastoreIdList {g Description         Property   System.String Description {get;} DrsAutomationLevel  Property   System.Nullable`1[[VMware.VimAutom FloppyDrives        Property   VMware.VimAutomation.Types.FloppyD FolderId            Property   System.String FolderId {get;} Guest               Property   VMware.VimAutomation.Types.VMGuest HAIsolationResponse Property   System.Nullable`1[[VMware.VimAutom HardDisks           Property   VMware.VimAutomation.Types.HardDis HARestartPriority   Property   System.Nullable`1[[VMware.VimAutom Host                Property   VMware.VimAutomation.Types.VMHost HostId              Property   System.String HostId {get;} Id                  Property   System.String Id {get;} MemoryMB            Property   System.Int32 MemoryMB {get;} Name                Property   System.String Name {get;} NetworkAdapters     Property   VMware.VimAutomation.Types.Network Notes               Property   System.String Notes {get;} NumCpu              Property   System.Int32 NumCpu {get;} PowerState          Property   VMware.VimAutomation.Types.PowerSt ResourcePoolId      Property   System.String ResourcePoolId {get; UsbDevices          Property   VMware.VimAutomation.Types.UsbDevi VMHostId            Property   System.String VMHostId {get;} VMSwapfilePolicy    Property   System.Nullable`1[[VMware.VimAutom

That's more like it. 

Get-PSDrive

OK, I had no idea this command existed. I had no idea half of these drives existed. This is exciting. 

In a UNIX prompt, you have an environment that's set, and you can examine the variables with the command 'env'. It'll print all of the environmental variables and their values for you. Well, you can do the same thing in PowerShell by typing: 

dir env: 

That's because….get ready for this…the environmental variable space is mapped like a drive. Yes. You can navigate the space and see variable names, and when you cat the files, you get the values. This is currently rocking my world. And there are more drives to explore! 


I learned a ton of new tips and tricks that are going to make my existence at the Windows command line much more fun. If you go have to deal with Windows servers and you still hate it, I'd highly recommend learning PowerShell if you don't already know it. Steven does a tremendous job teaching it, and I highly recommend picking up his class next year at LISA, where I'm certain that it will be offered. 

If you weren't able to come to LISA this year, you might consider purchasing the video stream from USENIX. The price for this four hour class is $325 and you don't even have to get out of your desk chair.