Saturday, May 4, 2013

PowerShell interview questions and Literacy

PowerShell Literacy

What is PowerShell Literacy? PowerShell Literacy centers on being PowerShell "literate" - that is, being able to read, understand, and grok PowerShell. PowerShell literacy isn't just being able to read PowerShell, but being able to think in PowerShell.
Many of us come to PowerShell from VBScript. Others from unix shell scripting. Others have been all GUI with a dash of batch files. PowerShell inherits much from these various predecessors, but PowerShell written from these perspectives oftenleads to solutions that even a mother couldn't love - so we're going to start off at the basement level.
Why read this? It's true that there are many PowerShell books out there, in print and online, and many of them are great. This one focuses on making you self-sufficient at PowerShell. If you're a doer, you will go far with this book as it will give you the few tools you need to get moving. If you need all the details, or if you need tons of script examples, then this probably isn't the book for you.
This quick tutorial will build up a beginner's PowerShell knowledge from thebasement level. I hope that this text can teach a beginner not just syntax, and not just code examples for how to do cool stuff, but actually to teach an understanding of PowerShell... An understanding of how the language works, and also how it can be used to do work for you.
C:\Users\Daniel> powershell
PS C:\Users\Daniel >
1. Enter: PowerShell
To start PowerShell, simply open a normal command prompt and run the command powershell. Alternatively, run powershell in the Run prompt (or within Windows 7's text input in the Start Menu).
In short, PowerShell is Microsoft's new shell and scripting language for use in managing Windows. It combines some of the best lessons learned from decades of UNIX administering, and deep integration with the Windows environment. Since it's built on Windows, its design and functionality directly addresses the challenges and benefits of working within Microsoft's operating systems.
Get used to the above prompt. It's the "interactive" shell way of working with PowerShell. We're going to spend the majority of this text beating this prompt into submission.
PS > "Oi, mundo!"
Oi, mundo!
2. Exchanging pleasantries
Above is a simple "Hello World" in PowerShell.
If you type a string literal (a string in quotes) into PowerShell, it will interpret it as a string. Note that both double-quotes (" ") and single-quotes (' ') are accepted in PowerShell (but they have slightly different functionality - more on that later!).
Similarly for numbers:
PS > 4
4
PS > 1+1
2
PS > 3/2
1.5
Note that when you divided two integers, PowerShell smartly converted the result into a floating point number. This is called "widening" the type, and is expected and welcomed in a shell environment - but may be a shock to traditional developers.
Shell veterans, both from Windows and UNIX, should feel right at home in PowerShell - commands such asdircd, and ls all work in PowerShell out-of-the-box.
PS > "this is no ordinary string - it's an object!".ToUpper()
THIS IS NO ORDINARY STRING - IT'S AN OBJECT!
3. Ditch the string, embrace the object.
The shell in PowerShell is object-based, rather than text-based. In a UNIX shell and in cmd.exe (Windows's native command-line program), when you run a command - you get a resultant string. When you run a command in PowerShell, you actually get a .NET object. But what does that distinction really mean?
Let's look at the above command again. We've created a string - everything within the quotes. But actually, we created a string object - a bunch of information in the computer which represents the idea of a string - rather than just a bunch of adjacent characters.
So after we create that string object, we use syntax similar to C# to run the ToUpper() method of the string. Like other OO programming language objects, objects in PowerShell have properties (values) and methods (procedures that do stuff). We're running the ToUpper() method, which outputs an uppercase version of the string. Note that running this method didn't actually change anything about the object or the string it represents.
The text that you see on your screen is a formatted text representation of the object, rather than the object itself.
Objects. Not text. This is a big deal. For real. "Why?" Read on...
PS > ps
PS > (get-process)[0].processname
ACEngSvr
4. Objects - shell works for you, you don't work for the shell
For UNIX admins, ps is all-too-familiar. This command will return a bunch of useful info on all of the running processes on the computer. PowerShell has its own version of ps. If you run ps, you should see an output that is quite similar to what UNIX offers. But then take a look at the second statement. Note that get-process is the formal name for ps in PowerShell. Don't worry too much about the syntax for now - basically what we are doing with [0] is asking for just the first process in the returned list.
The important bit is the .processname. In UNIX, if we wanted to get the name of a process, we would need to use some kind of regular expression to extract it out of the text blob returned by the shell. In PowerShell, however, we can simply ask for it. Using the dot operator ( . ), we can attack properties directly without any hacky work.
So, objects will let us access member properties of our outputs much easier. It also lets us access their member methods (the do-stuff pieces). This lets us interact with our output without thinking too hard - we can save that brain power for solving problems.
On top of all that, these objects are special even among objects. These objects are derived from the .NET Framework's objects. To non-Windows-developers, this won't mean much. We'll see later on, however, why this makes PowerShell much more powerful than if it had just implemented its own custom objects.
PS > get-location
PS > get-childitem -path c:\
PS > get-service
5. cmdlets - native PowerShell commands pack a punch
So far, we've seen how PowerShell handles numbers and strings, and how it can understand typical shell commands. But PowerShell wouldn't be its own beast without it having its own, native commands.
These native PowerShell commands are called cmdlets (pronounced command-lets). For the geeks wondering, cmdlets are compiled .NET code, which makes them optimized and very fast.
Cmdlets look and operate like command-line utilities in other shells. As such, the syntax is similar. Cmdlets can take in named parameters (like the "-newest 5" below), or positional parameters (which are interpreted based on position and don't require being named, such as "Application" below).
PS > get-eventlog Application -newest 5
The inputs for cmdlets don't have to be primitives such as strings or numbers (like the above example), and instead take objects as inputs. Likewise, they output objects. We saw this in the case of get-process, and the same is true for all of the above cmdlets as well.
One neat design choice in PowerShell cmdlets is the standardized naming convention. All cmdlets have a "verb-noun" format. The noun is a thing, and the verb is what is being done to the thing. get-process is a cmdlet that gets (and outputs) processes, while get-eventlog gets items from the Event Log. This makes it super-easy to read and immediately understand cmdlets, even if it's the first time you come across them. Neat, huh?
PS > get-help get-process
6. We all need help sometimes. For those times, make get-help your friend.
If you're hoping to be self-sufficient in PowerShell, this is the most important page in the book. get-help is the most useful cmdlet in PowerShell, and you just need to accept this as gospel.
get-help fills the same role that "man" pages do in UNIX. get-help gives a brief description of a cmdlet, allowing you to quickly learn new cmdlets from within PowerShell, rather than jumping out to a book or online reference.
"Brief", you say? Unimpressed? Ok then, try this on for size:
PS > get-help get-process -detailed
Boom. Description plus sample uses. This is the most important lesson I can give you. Try get-help on some of the other cmdlets we've used so far. Or, if you're feeling adventuresome, use it to check out some of the other available cmdlets:
PS > get-help get*
PS > get-help *item*
PS > get-help *
PS > "this is not a string, it's a string object" | get-member
7. get-member, or: second-most-important is still really important
Remember how I used the ToUpper() method on a string in a previous example? Ever wonder how I knew about that method? Wonder no more. Let me introduce you to get-member.
get-member is nearly as important as get-help. Where get-help gave you assistance on unfamiliar cmdlets, get-member will give you information on unfamiliar objects. get-member will tell you the name of the object type (in above case, System.String) as well as all of the methods and properties of the object. You can then pummel the object with the dot operator and cool methods.
PS > get-location | get-member
PS > (get-location).drive
PS > (get-location).path
PS > (get-location).provider
Note: Another cool command for learning about PowerShell is get-command. Why not use get-help to find out how to use get-command?
PS > "wait a second... what's that bar over there? " | get-member
8. The internet is a series of tubes, and so is PowerShell
Observant readers were probably asking what the hell syntax I used in the previous example with get-member. Non-observant readers, take note: I used weird syntax.
Thus is the first documented usage of the pipe operator and the pipeline in PowerShell. UNIX admins, don't sleep through this section, as PowerShell's pipeline works in a fundamentally different way than UNIX's pipeline construct.
For those unfamiliar with the idea of a pipeline, it's a compact syntax for sending the output of one command as the input of the next. In UNIX, this meant that the string output (which is designed more for humans to read than computers) is forwarded on, while in PowerShell the actual object (which is easily understood by computers) is forwarded. In get-member's case, whatever object is to the left of get-member acts as input to get-memberget-member figures out all of the object's interfaces and then outputs that information.
This is where PowerShell's object-based nature really starts to change the game. In other command-line environments, advanced queries would require sophisticated (and brittle) text parsing. Now, the object is our best friend.
PS > get-childitem
PS > get-childitem | sort-object Name -descending

PS > "more pipelining" | get-member | format-list
9. Anatomy of a pipeline
So. The point of the above example is to show a real-world case where we may want to do a multi-level pipeline. First, we create an object that we're interested in. Then, we decide we want to find out more about its members, so we pipe it to get-member. The problem is, the "Definition" outputted by get-member is too long to be displayed. So, we pipe the member information into format-list, which is one of our formatting utilities - not unsurprisingly, this one outputs each part in a list.
The above diagram visually represents what's going on in the pipeline. Each step generates objects and forwards them to the right. When we get to the right-most cmdlet, it too forwards its output to the right - but the output hits a brick wall. In the shell, that brick wall is called out-defaultout-default is a handy cmdlet that runs at the tail of all of the commands we run. It takes whatever is left at the end, interprets it, and displays it to us on the screen.
If out-default didn't exist, all of our hard-earned output would still be stuck in computer-readable objects rather than human-readable representations of those objects. And that wouldn't be too useful, would it?
PS > get-process
PS > get-process | measure-object
PS > get-process | select-object -first 10
PS > get-process | sort-object PM -descending
10. The pipeline and the object are BFFs
I've told you (at least) two things so far that you've more or less had to take at face-value: the pipeline is a useful concept, and objects make using the pipeline that much easier. Now it's time to prove that these concepts make PowerShell a breeze to use.
Consider the sort-object command above. In a text-based environment, we would have needed to parse each line to get the "PM" value, then targeted our sort on that. Now, we just tell sort-object straight-up: sort on PM. It's such a common-sense idea that that those who haven't had the pleasure of using awkprobably can't understand why I'm harping on this. If that's you, praise your luck and stick with PowerShell where it's safe.
Let's look at some more examples:
PS > get-process | format-table ProcessName, PM, CPU -autosize
This is simple but powerful. format-table will format the incoming objects in the pipeline into a table. By providing specific properties as positional parameters, we're telling it that we don't want the standard selection of properties, and instead the ones we selected. The -autosize switch tells format-table to read in all of the objects, and then determine the best width for the columns (note that -autosize means that format-table can't "stream" - streaming is where a cmdlet deals with each object as it receives it; in this case, format-table has to wait until it goes through them ALL before it begins its work. With large collections, it means there will be a pause before output will be written to the screen).
PS > get-process | where-object { $_.PM -gt 10MB }
Now we introduce some new syntax. The { ... } bit is called a scriptblock. Within the curly braces can be any number of PowerShell commands (if they are inline, use the semicolon (;) to separate them).
The $ symbol is the variable symbol in PowerShell. Every variable name must begin with a dollar sign - for example: $var1$var2$abcdefg are all valid variable names, but var3 is not. $_ is a special variable. It translates to "whatever object is in the pipeline".
With where-object, we are filtering the incoming objects based on the criteria listed in the scriptblock. In this case, we check the PM property of each object in the pipeline ($_.PM) and see if it is greater than 10MB. Note that 10MB is automatically translated by the shell to equate to 10485760 - the KB and MB modifiers exist in PowerShell to make administrators' lives easier.
PS > get-process | foreach-object { $_.CPU }
Another use of the scriptblock. In this case, rather than filtering based on the scriptblock, foreach-objectwill execute the scriptblock against EACH object (remember that $_ means "whatever object is in the pipeline right now"). In the above case, the action is simply to output CPU of each object - a pretty lame example. But check out this more advanced version:
PS > get-process | foreach-object -begin { $sum=0 } -process { $sum = $sum + $_.CPU } -end { $sum }
Neat, huh? The process scriptblock runs against each object (like the single scriptblock did in the previous example). The begin scriptblock is ran just one time, BEFORE any objects are processed; end is ran just one time, AFTER all objects are processed. The above example initializes a variable, $sum. Then the CPU of each object is added to $sum. Then we output the variable $sum. All in a very compact syntax.

PS > ps | sort PM -descending | select -first 10 | % -begin { $sum=0 } -process { $sum += $_.CPU } -end { $sum } | write-host -foregroundcolor DarkGreen

11. pipe | pipe | pipe | pipe | pipe
Don't panic. Breathe. Let's walk through this slowly.
PS > ps
Ok. No big deal. ps is just an alias for get-process.
PS > ps | sort PM -descending
We're still ok. sort is an alias for sort-object. This is the same command we ran in the last example: we're sorting all objects based on the PM property, and putting them in descending order.
PS > ps | sort PM -descending | select -first 10
Now, we take that sorted list and run select (alias for select-object) to grab just the first 10 results. Note that this gives us the top-10 objects based on PM.
PS > ps | sort PM -descending | select -first 10 | % -begin { $sum=0 } -process { $sum += $_.CPU } -end { $sum }
Now, using the very-compact % alias for foreach-object to accumlate the CPU of the top-10 objects based on PM. This takes the pipeline's many objects and reduces them to a single integer. (foreach-object gets such a kickin' alias because it's used so often in common tasks; we can all only aspire to be so awesome.)
PS > ps | sort PM -descending | select -first 10 | % -begin { $sum=0 } -process { $sum += $_.CPU } -end { $sum } | write-host -foregroundcolor DarkGreen
Finally, for some flair, we send that integer through write-host (a cmdlet that writes objects to the display) and setting the text color to DarkGreen. So in total, how would you describe what we did?
-> In Dark Green text, we displayed the combined CPU of the 10 processes with the most Physical Memory usage.
That complex idea was represented - clearly and concisely - in PowerShell due to the pipeline and its object-based nature.


To be effective with PowerShell, you need to start to actually think in PowerShell. You need to be like The One and look at commands and visualize what's going on. You must, to coin a term, be PowerShell Literate.
Following this intro are a bunch of PowerShell one-liners. It's your job to understandwhat each line is doing, and to be able to articulate it in words to yourself or someone else.
Describe the objects that are created, how they are passed through the pipeline, what kind of object is outputted or what is displayed. Strive to really describe what you see. Start to see the patterns of usage in PowerShell.
If you see something new or you simply have forgotten what a cmdlet does or how it works, feel free to use get-help to learn more about the cmdlet. This functionality will be available to you in the real world, and there's no penalty for using it here, if reading the help file gives you the key info to describe the command fully.
Give each example a try, then click on the example to see an explanation.
29. PS > get-content users.txt | sort-object -unique
30. PS > get-childitem cert:\localmachine\root | where-object { $_.subject -like "*Trust Network*" } | where-object { $_.notafter -gt (get-date).addyears(10) } | ft Subject, friendlyname
31. PS > dir env: | where { $_.name -like "user*" }
40. PS > new-psdrive "scripts" -psprovider filesystem -root "C:\users\bill\scripts\powershell"


Here are some sample PowerShell interview questions. These are the kinds of questions that could be asked to gauge one's basic literacy and comfort level with PowerShell.
Some things to keep in mind:
  • In general, interview questions are meant to be relatively quick - quick to ask, and quick to answer.
  • As such, the solution should be straight-forward - worry about efficiency and clever tricks later.
  • These questions are mostly technology-agnostic, aside from Windows and PowerShell themselves (no Exchange, IIS, SharePoint, etc. -based questions).
  • There may be many ways to solve a problem, the solutions provided are just one interpretation and solution.
Give each question a try. As in an interview, you can get a hint in the right direction by clicking the Hint button  To see a solution, click on the text of the question.
1. Basic literacy. Describe the following:
a. What is PowerShell? Why is it called a shell?
b. How does PowerShell differ previous Windows scripting techniques, such as CMD/batch files, VBScript, etc.?
c. What is a cmdlet?
d. What is meant when it's said that Powershell is "object-based"?
e. What is the pipeline? How is it useful?
[None]
2. How would you find the name of the local computer?
Environment variable
3. Convert the number 11867 into hexadecimal. Now, convert the hex value 0x1aab to decimal (base-10).
Part 1: Convert to a string; Part 2: Don't think too hard.
4. Get the amount of free space on the C drive.
WMI is an option
5. Count the number of lines in a file, excluding blank spaces.
3 Steps: Get all lines, filter out blanks, count what's left.
6. Get names of all "Manual" services that aren't running. All that are.
WMI - unfortunately get-service doesn't have StartMode info
7. Read in a text file, replace all social security numbers with ***-**-****.
PowerShell has a built-in -replace operator.
8. Get all running processes using over 10MB of (physical) memory. Save this info to CSV file.
get-help *process*; get-help *csv*
9. Look in a directory, return all txt files that have a name of the pattern: 4 letters, followed by 3 numbers.
Perhaps too complex pattern for get-childitem's -filter
10. Look at the recent log files in a given directory (extension ".log") - those modified within the past 24 hours. Search for the word "ERROR", and return the lines that contain ERROR.
Tackle each step in order, using pipeline to your advantage -- can be done with a 1-liner
11. Get the number of processors/cores on your system. Get the clock speed of the processor(s).
WMI is a good place to start when looking for system info
12. Assume you have a file with a bunch of records - names, or phone numbers, or GUIDs, etc. Read in that file, remove all duplicate records.
Get the contents, then pipe to... some cmdlet
13. Download a website (http://www.zappos.com/), return all of the phone numbers on the page.
WebClient to download, then match on the pattern
14. Get every other line in a text file (ie. 1st, 3rd, 5th lines...)
Remember that array indeces go 0, 1, 2, 3...
For loop is one possibility, but can also be done with pipeline approach.
15. Load an XML document from file. Find all of the nodes of a particular type wherever they are, and get the inner text. For example, get all of the "price" nodes.
Use XPath syntax to get nodes.
16. Get events from System event log referring to services entering "running state". Limit to only the most-recent hundred entries in System.
Look at the Message property of each event
17. Read in numbers from a text file (one integer per line). If the number is greater than 10, print the number in green text; else, print it in red.
[int] | get-member -static
write-host
18. Use netstat to get all open network connections. Filter to just those "LISTENING".
netstat -a
Remember - netstat is a legacy CMD utilty, and will return a big blob of text rather than objects.
19. How many seconds are in the next year?
When subtracting two DateTime objects, a TimeStamp object is returned
20. Get the running services on a remote machine. How would you do it if you don't have PowerShell V2?
Without V2, fall back on WMI

No comments:

Post a Comment