PowerShell for Admins

PowerShell for Admins
ScriptingWife
PowerShell for Admins

Charlotte User Group July Meeting

Please join us on a special date in July. This month our meeting will be on July 11, 2013 instead of our normal first Thursday of the month due to the holiday.
Microsoft Scripting Guy Ed Wilson will make a presentation on DSC Desired State Configuration for PowerShell V4.
Sign up at the following link in Meetup so we know how many will be there and we can have adequate food for all.
http://www.meetup.com/Charlotte-PowerShell-Users-Group/events/124356442/

Don Jones
PowerShell for Admins

Meet the Scripting Games Judges: Olver Lipkau

I have been working for AtoS, formaly Siemens IT Solutions and Services, for 6 years as a IT Consultant.
I was 15 when I started scripting. First only batch scripts to automate simple things. With time the scriptt grew in complexity and languages. VBS, AutoIt, AHK and finally PowerShell, which superseeded all others. PowerShell became a passion and became more and more a daily thing.
I was invited to be a judge for the Scripting Games in 2011, 2012 and now 2013.
You are welcome to visit my Blog at http://oliver.lipkau.net/blog and check out what I have been up to.

Art Beane
PowerShell for Admins

Some notes on Event 2 Advanced

I hate to seem negative, but I’ve noticed a few things about a number of the advanced entries that seem like folks didn’t read the instructions, or just weren’t careful about details.
There were a surprising number of entries that had [string]$ComputerName instead of [string[]]$ComputerName in the params section and then went on to treat the parameter as if it were an array.

  • Somewhat related to the array issue, the problem statement indicated that there could be several files that had computer identification for piping into the solution. Several scripts went beyond the minimum by accepting a filename property to process those files directly. I don’t think that extension is out-of-bounds, but  scripts that accepted only filenames and excluded ComputerName input didn’t get my vote.
  • The instructions asked for a “full help display”, but many of the entries had fairly limited documentation. One thing I especially missed was a .PARAMETER description.
  • My last negative comment is about parameter names. Although there’s nothing in PowerShell to prevent it, best practices in parameter names should be followed. The parameter ought to be $ComputerName, not $Name, $Server, $Computer, etc. I know it’s easier with verbs and nouns because of the Get-Verb and Get-Noun cmdlets, but please pay attention to how you name your parameters.

On the whole, though I really liked the effort everyone put into their scripts. Those that exactly met the requirements were short, sweet, and to the point. There were several extensions that I also liked.

Art Beane
PowerShell for Admins

Notes on Beginner Event 2

 First of all, congratulations! It looks to me like a lot of learning is going on; the 2nd event entries look really good to me. I especially liked the way a number of you built up a one-liner by starting with a_ Get-WmiObject Win32_ComputerSystem -ComputerName (Get-Content file.txt)_ and piping it into Select-Object to generate the data. However, there were a couple of areas within the Select block that make me think that some more discussion of what $_ means in a pipeline would be helpful.
Within the Select block, it is necessary to make a call to Get-WmiObject Win32_OperatingSystem to get come additional information. It looks like everybody got the format correct: @{Name=‘OS’;Expression={Get-WmiObject}} where folks got into trouble was in specifying the ComputerName property. Some didn’t even include it, meaning that the OS value would be taken from the local computer and not the remote one. But, more often than not, the code contained a plain $_ : @{Name=‘OS’;Expression={(Get-WmiObject Win32_OperatingSystem -ComputerName $).Caption}}. So, what’s wrong with this? The problem is the value of $ at this point in the pipeline.
Let’s try an experiment to show what I mean. Try this:

June Blender
PowerShell for Admins

Placing Comment-Based Help

What an amazing event. I’m now reading through each of the Advanced entries in a vain attempt to whittle the entries down to a short list. It’s an incredibly difficult task, which is testament to your skill and diligence. We are so lucky to have so many competent scripters in the community.
As I read through the comments on each script, I’ve noticed several that say:
“Help should be nested under the function to work properly.”
Au contraire! This is not true and I want to make sure that people who see this comment are not misled. The Windows PowerShell team designed comment-based help to be really flexible.
As I explained in about_Comment_Based_Help, you can put comment-based help for a function in one of three positions:

Art Beane
PowerShell for Admins

Judge Notes for Event 1

 A lot of you have been working too hard at solving the problem (both beginner and advanced). Some of this is clearly related to trying to offer a very complete solution but some look like attempts to write extra clever or elegant code. In the “real world”, there"™s probably not enough time or interest in putting lots of effort into these extras. The minimum it takes to achieve the goal is most often good enough. Here are a couple of examples to illustrate this (with the intent of providing a learning opportunity).
Working with the destination folder address.
A common error here was missing the subdirectory. Most folks got this correct by using some version of $.FullName.Replace("˜C:\Application\Log"™,"™\NASServer\Archives"™)_ or Join-Path “˜\NASServer\Archives”™ $.Directory.Name_, but there were a number who just used the root destination folder name without looking for the subfolder. And some others had solutions that (although I thought were innovative), took too much effort. Among them are:

Don Jones
PowerShell for Admins

Why Doesn't My ValidateScript() work correctly?

I’ve received a few comments from folks after my observations on the Scripting Games Event 1. In those observations, I noted how much I loved:
[ValidateScript({Test-Path $_})][string]$path
As a way of testing to make sure your -Path parameter got a valid value, I love this. I’d never thought of it, and I plan to use it in classes. I may write a book about it someday, or maybe even an ode. Seriously good logic. But… I also bemoaned some scripts that provided an additional Test-Path, in the script’s main body of code. Why have a redundant check?
So, first, thanks for the e-mails you all sent. Second… please understand that I can’t respond to you all. I’ve got this full-time job thing, and I’ve got to do it or the grocery store will stop taking our checks. You’re welcome to drop comments here, and I really appreciate when you say stuff like, “can you explain ___ in a future post?” because it gives me ideas to write about. I just can’t get into private e-mail based education for a dozen folks. Teaching is kinda what I do for my job, so most of my time has to go to that.
But - there’s a great teaching point here. Let’s take this example:
valid-default-path
This works as you would hopefully expect. When given a valid path, it’s fine. When allowed to use a valid default, it’s fine. When given an invalid path, it barfs in the ValidateScript. Now look at the next example - which more closely approximates what people have been seeing in their Scripting Games scripts:
invalid-default-path
In the Games, you were given a default path that wasn’t valid on your computer. So folks allowed their script to run with that default, and got errors, and were annoyed that ValidateScript() didn’t catch the problem.
It never will.
When you run a command, PowerShell goes through a process called parameter binding, wherein it attaches values to parameters and runs any declarative validation - like ValidateScript(). That validation will always catch invalid incoming data that’s been manually specified or sent in via the pipeline (for parameters that accept pipeline input). Because my -Path parameter wasn’t declared as mandatory, the validation routine will let me run the script and not specify -path.
Then the shell actually runs my code - and that’s when it assigns the default value to $path if one wasn’t specified on -path. Validation is over by this point, so an invalid default value will sneak by. The assumption by the shell is that you’re providing the default value, so you’re smart enough to provide a valid one. If you don’t, it’s your problem.
So do you just add a second, in-code check for the parameter? I’d still say no. I really dislike redundancy. If you know, because of your situation, that you can’t rely on ValidateScript(), then don’t use it at all - one check should suffice, and if it needs to be in-code instead of declarative, that’s fine. What’d be nice is if there was a declarative way of specifying a default, like [Default(‘whatever’)] that ran before the validation checks, but such a thing doesn’t exist. Frankly, you could probably argue that if you can’t guarantee the validity of a default, then you shouldn’t provide one - and I’d probably buy into that argument, and subscribe to your newsletter.
In this case, the problem is entirely artificial. The default path value given to you in the Games scenario is valid in the context of the Games; it’s just when you test it on your system, outside that context, that a problem crops up.
Hopefully this helps explain how the ValidateXXX() attributes work, and how they interact with other features, like a default value.
Now explain why this will never assign C:\ as a default value:
[Parameter(Mandatory=$True)][string]$path = ‘c:'

Enrique Puig
PowerShell for Admins

Comparing SQL Server table schemas with PowerShell

As a SQL Server DBA or SQL Server developer sometimes is necessary to know whether two tables have equal schemas or not. For example, a few months ago I had to consolidate two SQL Server instances in just one. One of the main problems were the collisions between Databases and Tables. I found out that both instances had Databases with equal name and the same thing happened with tables inside those databases. When consolidating databases is very important to make sure that users and apps will find the same schema they were used to find before consolidation, so in order to consolidate databases it will be necessary to find tables with different schemas, merge them and solve conflicts.

Don Jones
PowerShell for Admins

What are Your PowerShell Newbie Gotchas?

I’m putting together a list of common “gotchas” for PowerShell, mainly things that affect newcomers. So far, I’ve got:

  • Piping the output of a Format cmdlet to nearly anything else
  • Using -contains instead of -like
  • Selecting a subset of object properties and then trying to sort/fiter on a now-missing property
  • Wrong syntax for -filter parameters on various commands
  • Commands that don’t produce pipeline output (e.g., piping Export-CSV to something)
  • Using ConvertTo-HTML without -Fragment and appending multiple pages in one file
  • Confusion with ( [ { and the other punctuation
  • Concatenating strings (hard) vs. using double quotes (easier)
  • $ not being part of the variable name (esp with -ErrorVariable)
  • Accumulating objects in a variable and returning it, vs. outputting to the pipeline directly

What are your “gotchas?”

Don Jones
PowerShell for Admins

Coming: Tips for the Scripting Games

In preparation for the upcoming Scripting Games, the April 2013 issue of the free PowerShell.org TechLetter will feature tips, examples, and advice for helping you do the best in the Games! Remember that the Competitor Guide is now available, so you can start reviewing how the Games will be graded (by the community) and judged this year.
If you’re not already receiving the TechLetter, [subscribe by April 15th][3] to receive the April issue in your Inbox!