PowerShell for Developers - Cmdlets

Cmdlets (Command-lets) In PowerShell we have a concept called Cmdlets, these are the functions we use. We’ve already seem some of them, but this chapter will introduce you to the must-know Cmdlets. This is not a catalog of all Cmdlets, not even close. As of PowerShell 3.0 there are 2,430 in Windows Server 2012, without adding those available from the community. Microsoft’s commitment is unfailing, they’ve committed to shipping PowerShell Cmdlets for every server product. If you use SQL Server, Exchange, BizTalk, SharePoint or any of the other server products then you simply cannot do anything more powerful to pump up your career than to learn PowerShell. Proper Grammar Cmdlets have a grammar all of their own. In PowerShell we are encouraged to use a grammar of Verb-Noun when creating Cmdlets and functions. But more than that, there is a list of common verbs, which help new users discover your functions. For instance, I created a function to update the value of an AppSetting in a web.config or app.config file. Now, I’ve not memorized the whole list of verbs, so how did I know which one to use? Well, I used the Cmdlet called Get-Verb like so: Hmm… I wonder if it should be called Create-AppSetting: > Get-Verb C* Verb Group ---- ----- Clear Common Close Common Copy Common Checkpoint Data Compare Data Compress Data Convert Data ConvertFrom Data ConvertTo Data Complete Lifecycle Confirm Lifecycle Connect Communications Nope, no listing for Create. How about Set-AppSetting: > Get-Verb S* Verb Group ---- ----- Search Common Select Common Set Common Show Common Skip Common Split Common Step Common Switch Common Save Data Sync Data Start Lifecycle Stop Lifecycle Submit Lifecycle Suspend Lifecycle Send Communications Alright, yep, that could work. But I’m curious, how about Update-AppSetting? > Get-Verb U* Verb Group ---- ----- Undo Common Unlock Common Unpublish Data Update Data Uninstall Lifecycle Unregister Lifecycle Unblock Security Unprotect Security Use Other Bingo, Update-AppSetting is a good choice, so is Set-AppSetting. I chose Set-AppSetting, but either would have been an excellent choice. Likewise, if you were to look-up Delete: > Get-Verb Delete > Nope, not there. How about Erase? > Get-Verb Delete > Get-Verb Erase > Nope again. How about Remove? > Get-Verb Delete > Get-Verb Erase > Get-Verb Remove Verb Group ---- ----- Remove Common There it is! So remember, use Get-Verb when deciding how to name things, it will help everyone out in the long run. For-Each So what is the most important Cmdlet in PowerShell? Well, for sheer utility, I’ve got to give this award to ForEach-Object. It allows you to iterate over any array or list of data. So how do we use it? > 1,2,3,4,5,6 | ForEach-Object { Write-Host $_ ($_ * $_) } 1 1 2 4 3 9 4 16 5 25 6 36 Alright, we’ve got one call to the script block (inside the { }) for every member of the array. Now, you might be thinking, “man that is really verbose for a scripting language”, well good news that is the really long form version of that command. Shall we terse it up a bit? First, ForEach-Object has an alias (more on those later) in simply %. So we can shorten it up like so: > 1,2,3,4,5,6 |%{ Write-Host $_ ($_ * $_) } 1 1 2 4 3 9 4 16 5 25 6 36 Pretty good, but we can get even better. We’re explicitly calling Write-Host, but whatever is returned at the end of a command is automatically printed to the host. So we can shorten it further like so: > 1,2,3,4,5,6 |%{"$_ $($_ * $_)"} 1 1 2 4 3 9 4 16 5 25 6 36 Alright, I can hear you already, hold up Mr. Smarty Pants, you just did something tricky there. Yep, I sure did. How did that work? Let me explain. Any string in double-quotes (" ") will have any variables ($foo) inside of it replaced with the value of that variable. Moreover, any script block returns the last object it creates by default, so since that script block creates a string, it returns that string. And ForEach-Object collects those objects and returns them as an Array, here to console, but it could also be piped to yet another Cmdlet or function. But, the really attentive among you will be saying, “Wait! You slipped in another $.” Your right, but lets see it without that extra $. > 1,2,3,4,5,6 |%{"$_ ($_ * $_)"} 1 (1 * 1) 2 (2 * 2) 3 (3 * 3) 4 (4 * 4) 5 (5 * 5) 6 (6 * 6) Ah, you see, this version doesn’t actually perform the multiplication. It replaces the $_ with each value, but the rest is just considered a string. But PowerShell has a way to evaluate expressions in the middle of strings as well, using $( expression ). So the extra $ in this 1,2,3,4,5,6 |%{"$_ $($_ * $_)"} version evaluates the multiplication and gives us our “most terse form” of this command. Where-Object So we’ve now seen how to iterate over an array, but the other thing we usually need to do is to filter them. In .NET, we are used to using LINQ for this, but LINQ is pretty verbose itself. How about we cut down our list of numbers to just the even numbers using Where-Object: > 1,2,3,4,5,6| Where-Object { ($_ % 2) -eq 0 } |%{"$_ $($_ * $_)"} 2 4 4 16 6 36 Outstanding, but verbose. Well just like with For-Each above, there is a much shorter alias for Where-Object which is ?. That shortens us up to: > 1,2,3,4,5,6|?{ ($_ % 2) -eq 0 } |%{"$_ $($_ * $_)"} 2 4 4 16 6 36 A little diversion… Now, we’ve seen how to limit the array, but here’s a little diversion. At the current time we’re returning an array of strings. Actually, since all arrays in PowerShell are arrays of Objects (in C# Object[]), this would be an array of objects consisting entirely of string objects. Prove it? Sure. First the type of the array itself: > (1,2,3,4,5,6|?{ ($_ % 2) -eq 0 } |%{"$_ $($_ * $_)"}).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array And now the individual members: > 1,2,3,4,5,6|?{ ($_ % 2) -eq 0 } |%{"$_ $($_ * $_)"} | %{ $_.GetType() } IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object True True String System.Object True True String System.Object But what if I wanted to have access to each of those numbers (the number itself, and the square) at the end of the command. One way to do this would be to create a Hashtable instead of a String like so: > 1,2,3,4,5,6|?{ ($_ % 2) -eq 0 } |%{@{Num=$_;Square=$_ * $_}} Name Value ---- ----- Num 2 Square 4 Num 4 Square 16 Num 6 Square 36 Let’s check the types: > 1,2,3,4,5,6|?{ ($_ % 2) -eq 0 } |%{@{Num=$_;Square=$_ * $_}} | %{$_.GetType()} IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Hashtable System.Object True True Hashtable System.Object True True Hashtable System.Object Yep, Hashtables. But sometimes have to name variable when you don’t intend to use those names is a bit annoying a verbose. So instead, we can create an array by simply using the ,@( ) array constructor syntax: > $a = 1,2,3,4,5,6|?{ ($_ % 2) -eq 0 } |%{,@($_,($_ * $_))} > $a 2 4 4 16 6 36 Uhm, output looks a little wierd. Lets take a look at the type of $a: > $a.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array Ok, an array. And it’s members? > $a | %{ $_.GetType() } IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array True True Object[] System.Array True True Object[] System.Array Alright, more arrays! And inside the first one of those? > $a[0] | %{$_.GetType()} IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType True True Int32 System.ValueType Boom, Int32s for the win. Instant multi-dimensional array. This is powerful, it is a terse syntax which is similar to Tuples in other languages. Because they are Object[] arrays, the types don’t have to match. Oh yeah, did I mention there is a short form for creating arrays of concurrent integers? Ohm, my bad. For instance: > $a = 1..6|?{ ($_ % 2) -eq 0 } |%{,@($_,($_ * $_),"Smile")} > $a.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array > $a | %{ $_.GetType() } IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array True True Object[] System.Array True True Object[] System.Array > $a[0] | %{$_.GetType()} IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType True True Int32 System.ValueType True True String System.Object Get-ChildItem The last Cmdlet I want to introduce in this chapter is the one most people use without even knowing that they’re doing so. If you’ve every opened a PowerShell command prompt, you’ve likely done something like: > dir Directory: C:\Source\Highway Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 5/2/2013 2:20 PM Data d---- 5/4/2013 10:44 PM MVC d---- 5/4/2013 6:37 PM Onramper d---- 5/4/2013 6:46 PM Services -a--- 5/4/2013 11:59 AM 1062 dest -a--- 5/4/2013 12:11 PM 385 distribute.ps1 Or perhaps if you’re from the bash or other sh descendant family of shell users: > ls Directory: C:\Source\Highway Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 5/2/2013 2:20 PM Data d---- 5/4/2013 10:44 PM MVC d---- 5/4/2013 6:37 PM Onramper d---- 5/4/2013 6:46 PM Services -a--- 5/4/2013 11:59 AM 1062 dest -a--- 5/4/2013 12:11 PM 385 distribute.ps1 Now, in reality you’re using a Cmdlet called Get-ChildItem. Prove it? Sure: > Get-ChildItem Directory: C:\Source\Highway Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 5/2/2013 2:20 PM Data d---- 5/4/2013 10:44 PM MVC d---- 5/4/2013 6:37 PM Onramper d---- 5/4/2013 6:46 PM Services -a--- 5/4/2013 11:59 AM 1062 dest -a--- 5/4/2013 12:11 PM 385 distribute.ps1 Now this Cmdlet has so much power it almost deserves a chapter to itself. Let’s review just a few things that can’t be skipped over. First, this Cmdlet returns an array of FileSystemInfo objects. Of course that’s easy to prove: > ls |%{$_.GetType()} IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True DirectoryInfo System.IO.FileSystemInfo True True DirectoryInfo System.IO.FileSystemInfo True True DirectoryInfo System.IO.FileSystemInfo True True DirectoryInfo System.IO.FileSystemInfo True True FileInfo System.IO.FileSystemInfo True True FileInfo System.IO.FileSystemInfo That means we have access to all sorts of data about those directory items by pipeing that command along. For instance, what if I wanted the full path and filename? > ls |%{$_.FullName} C:\Source\Highway\Data C:\Source\Highway\MVC C:\Source\Highway\Onramper C:\Source\Highway\Services C:\Source\Highway\dest C:\Source\Highway\distribute.ps1 And if I wanted to get just the files? > ls -File |%{$_.FullName} C:\Source\Highway\dest C:\Source\Highway\distribute.ps1 And if I wanted their sizes instead? > ls -File |%{$_.Length} 1062 385 Another bonus section? Oh, ok… We can restrict the types of files to a pattern like so: > ls -File *.ps1 |%{$_.Length} 385 What if I wanted that same thing, recursively, through every subdirectory of my current location? > ls -File *.ps1 -Recurse|%{$_.Length} 10275 10424 4001 1332 1546 2987 332 188 2997 344 194 211 62 332 0 0 0 0 247 243 368 247 243 0 0 0 0 880 265 265 217 62 332 385 And … if I wanted all those summed up? > ls -File *.ps1 -Recurse|%{$_.Length}|Measure-Object -Sum Count : 34 Average : Sum : 38979 Maximum : Minimum : Property : Aliases There are a finite number of keystrokes left in your hands before you die. – Scott Hanselman So, you’ve likely picked up by now that I’m a fan of terse commands. Terse commands allow you to move faster, which to me is a huge part of why I’m investing in PowerShell. There is an ability in PowerShell to create shorter versions of Cmdlets, as you’ve seen already in this article, called Aliases. There are alot of aliases already defined. How many? So many I can’t just do a screen shot of them, but I can count them: > alias | Measure-Object Count : 150 Average : Sum : Maximum : Minimum : Property : 150 aliases already defined for you. If you want to see what command is behind something like dir you can simply: > alias dir CommandType Name ModuleName ----------- ---- ---------- Alias dir -> Get-ChildItem As you can see, dir is Get-ChildItem. What if I wanted to see all aliases for a given Cmdlet? > alias -Definition Get-ChildItem CommandType Name ModuleName ----------- ---- ---------- Alias dir -> Get-ChildItem Alias gci -> Get-ChildItem Alias ls -> Get-ChildItem Now, aliases are something you can expand on! You can make it super easy to open text files by aliases notepad.exe as so: > New-Alias n C:\Windows\system32\notepad.exe > n .\distribute.ps1 That opens Notepad, with the distribute.ps1 file already opened for editing. I keep aliases around for a lot of things. For my text editor, my text comparison tool, and so much more.

PowerShell for Developers - Intro

I must go down to the seas again, to the lonely sea and the sky, And all I ask is a tall ship and a star to steer her by, And the wheel’s kick and the wind’s song and the white sail’s shaking, And a gray mist on the sea’s face, and a gray dawn breaking. – Sea Fever by John Masefield Every developer knows that in order to be successful at their chosen profession, they need to keep the best tools at their disposal. We all have our favorite text editors, and our favorite comparison tools, and the wise among us also have our favorite scripting languages and command line environments. I am an unabashed fan of GIT, and as such for several years now I’ve used the bash shell as my command line environment of choice. But I recently started paying more attention to PowerShell and I realized that I had not at all given it it’s due when I first learned about it several years ago. I’ve spoken recently with @DevlinLiles, @AmirRajan, @CoriDrew, and @BForrest about this, and I realized that I wasn’t alone at all in this. Most developers working in .NET languages have mostly ignored PowerShell. I intend this series of blog posts to correct this issue. The Basics Let’s start at the very beginning A very good place to start When you read you begin with A-B-C When you sing you begin with do-re-mi – “Do-Re-Mi” by Rodgers & Hammerstein PowerShell 3.0 So how do I use the PowerShell thing, Tim? Easy. First, we need to know what version of Windows you’re using now, because we might want to upgrade you to the latest version. If you’re using Windows 8 or Windows Server 2012 then you’re good, you already have PowerShell 3.0. If you’re using Windows 7 or Windows Server 2008 or Windows Server 2008 R2, then you need to download the Windows Management Pack 3.0 which upgrades you to PowerShell 3.0. Not sure if someone else might have already installed it? Just open PowerShell (hint: Win+R -> PowerShell enter) and enter $host.version at the prompt. > $host.version Major Minor Build Revision ----- ----- ----- -------- 3 0 -1 -1 The above it what we’re looking for, anything else, and you need to install the Windows Management Pack 3.0. Variables The first thing you need to know about PowerShell is how to create a variable. This is very simple, you just assign it to a variable name. In PowerShell, all variables are preceded by a $. So if you want to create a variable X and assign the integer value 1 to it, you would type: > $X = 1 Important to know, especially for C# developers, is that PowerShell is case-insensitive. As such, $X is the same as $x. Value Types Now, .NET developers, pay attention to this. In PowerShell all variables are actual objects, not just string values. What do I mean? Type this: > $X.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType Holy smoke! That variable is an Int32, I mean a real System.Int32. Because of this, we can use any type of methods that might exist on those objects. For instance, we could type: > $X.Equals(4) False So how do we create non-value types then? That depends… Reference Types via New-Object Most of the time, we are used to creating .NET objects by typing something like var dt = new System.DateTime() but in PowerShell we have something similar, but different: > $dt = New-Object System.DateTime You can always check the value of a variable, just by typing it’s name at the prompt like this: > $dt Monday, January 1, 0001 12:00:00 AM That makes total sense, that is the default value of a DateTime aka default(DateTime) in C#. But in reality, I tend to use System.DateTime.Now to get the system time, more often than I do new DateTime(), so how to I do that in PowerShell? Reference Types via Static Properties & Methods So if we want to access the .NET Framework’s static types, we simply need to reference the type, and then the method, as follows: > [System.DateTime]::Now Monday, May 6, 2013 10:22:26 PM Now, if we wanted to assign that to our variable, we would just do: > $dt = [System.DateTime]::Now Please note, when we assign the value to a variable, we no longer get output to the console. We’ll see how to change that in just a bit. Arrays Arrays are common in all programming languages, they represent a series of values. In PowerShell, those values are not required to be of the same type, you can think of all Arrays in .NET terms as System.Object[], an array of Objects. Declaring and using arrays could not possibly be easier in PowerShell, we simply put together a series of values, separated by commas. > 1,2,3 1 2 3 As I noted above, they don’t have to be of the same type: > 1,"abc",[System.DateTime]::Now 1 abc Monday, May 6, 2013 10:28:15 PM And that is all there is to arrays. You can add members to arrays many ways, but the simplest is as follows: > $arr = 1,2,3 > $arr 1 2 3 > $arr = $arr + 4,5,6 > $arr 1 2 3 4 5 6 Hashtable There is one other type of object which is critical to the world of PowerShell, and that is the Hashtable. PowerShell is a dynamic language, in fact as of 3.0 it’s even built on top of the Dynamic Language Runtime, but as such it needs a flexible structure for storing loosely types objects. Enter the Hashtable. The syntax for Hashtable couldn’t possibly be easier, to create one you just use @{ key=value; key2=value2} So for instance, if you want to create a Hashtable to store a bunch of people, you could do so like this: > $tim = @{ FirstName="Tim";LastName="Rayburn"} > $cori = @{ FirstName="Cori";LastName="Drew"} > $barry = @{ FirstName="Barry";LastName="Forrest"} Now, as we learned in the last section, we can create an array just by separating items by commas, so lets do so, and then sort these people by FirstName: > $tim,$cori,$barry | Sort-Object FirstName Name Value ---- ----- LastName Forrest FirstName Barry LastName Drew FirstName Cori LastName Rayburn FirstName Tim As you can see, Barry is now listed first, then Cori, then Tim. Don’t worry about understanding Sort-Object just yet, we’ll get into how that line works more in the next post. Now, lets imagine I want to add a value for Employer to each of these. How to I change a Hashtable once it has been created? Easy, just refer to a property that doesn’t exist yet, and set its value. > $tim.Employer = "Improving Enterprises" > $barry.Employer = "Improving Enterprises" > $cori.Employer = "Improving Enterprises (Contractor until August)" Constants In addition to all of the above, there are a couple of constants which you might want to know about when developing. $null is the constant value of a Null Reference. In addition there are constants for $true and $false though if a boolean is expected you can also always use 1 or 0 respectively.

Working with Dynamic Schema in Azure Mobile Services

Lately I’ve been developing on a side project using the awesome Azure Mobile Services offering from Microsoft. Specifically I’ve been developing a Windows Phone 8 application, the details of which will be revealed in time. One of the best features of Azure Mobile Services is the ability to work with a Dynamic Schema, it will automatically insert new columns for fields it has never received before.