PowerShell and DevOps Summit 2016

Well another PowerShell Summit has come and gone. Although now we’re all grown up and are now the PowerShell and DevOps Global Summit. This year’s event was sold out and featured speakers from around the world as well as many people from Microsoft. In fact this is the only event where you can interact personally with members of the PowerShell and Windows Server product teams as well as get sneak peeks about what is coming. Even though most of the sessions were recorded and will eventually be made publicly available, not everything was recorded and of course you can’t capture the one-on-one nature of the event.

I enjoyed meeting old friends and making some new ones. I sat in on some very interesting sessions and have a number of new things to try out and play with if I ever get a bit of spare time.

I presented a 2 hour session that centered on how I rapidly build new PowerShell tools from existing commands. I received some terrific feedback and the session went well. I never know if what I’m presenting is what people are expecting or at the level they need but I think this session went well. The session was recorded and as far as I know eventually it will be posted online. I’ll share that information when it happens. In the meantime, I’ve assembled all of my demos into a zip file which you can download from here.

Next year’s event will be back in Bellevue, Washington most likely in April 2017. Don’t wait to register when you see it open.  A call for sessions will open up probably in the August-September time frame.

If you attended this year, I’d love to know what you thought, what you took away and what you think would make it an even more awesome event.

The Power of Custom Properties

The other day fellow PowerShell MVP Adam Bertram published an article about using custom properties with Select-Object. It is a good article in that it gets you thinking about PowerShell in terms of objects and not simple text. But I want to take Adam’s article as a jumping off point and take his ideas a bit further. I’m going to use Adam’s same example as a learning tool. Don’t get distracted by other ways to get the same information. The process and techniques are what matter here.

Whenever I’m working with PowerShell, I’m always thinking about how I can use this at scale.  How can I get this same information for 10 or 100 servers? And of course,  at this point I need to make sure I include a computername in the results.  First, I’ll try something with a single computer.

image

Close but not quite. Get-CimInstance is writing multiple objects to the pipeline.  The server in question has 2  8GB sticks of memory which is what you see in the output. I need something more along Adam’s original idea to that this becomes 16GB.

What I really want is the Sum property from Measure-Object and to that I need to add a Computername property. I’ll turn things around a bit.

image

This works because I’m using the common PipelineVariable parameter introduced in PowerShell 4.  What happens is that the pipeline output from Get-CimInstance is stored in a variable, pv, which I can access later in the expression. In my case I’m defining a new property for the computername using $pv and adding it to the selected output from Measure-Object.

However, if I try this for multiple computer names, I don’t get the expected result.

image

That’s because I’m adding up the physical memory instances from all servers, which isn’t really what I want. Instead, this is a situation where I have to process each computer individually.

image

One thing to be careful of when using the ForEach enumerator is that you can’t pipe the output to another cmdlet like Export-CSV, unless you explicitly save the results to a variable.

Then you can pipe $data to other cmdlets. You can use ForEach-Object although it might be little harder to follow.

But this makes it easier if you need to pipe the output to something else.

image

To wrap this up let’s go all out and define a few more custom properties.

image

Even though I’m selecting a few properties from the output of Measure-Object, I’m defining several others which are calculated on the fly. There is so much you can do with this technique,  but if I lost you anywhere please let me know.

Managing PowerShell Functions

Most of you probably know I’ve been using PowerShell since its beta days which now means I have about 10 years worth of PowerShell files. I find it hard to throw anything away. Over this time frame my PowerShell profile scripts have also grown, often loading functions that I’ve come up with. The effect has  been that it takes a little bit longer to bring up a new PowerShell console or ISE session. Since deep down I know there are functions I no longer use, I figured it was time for some profile cleanup. The first step was to identify my functions.

First, how many functions am I talking about? PowerShell stores currently defined and active functions in a PSDrive which means it is pretty easy to get a “directory” listing and count.

image

However, some of those functions are defined by Microsoft and other modules.

image

I don’t have any issues with functions defined from a given source. My problem is in that 100 that have no source.  Again some of those are defined by Microsoft which are fine. So I looked at one of them in more detail.

image

I noticed that these functions included a HelpFile. I knew that none of my functions didn’t. With this information I can get a directory listing and filter with Where-Object.

image

These are functions that are loaded from dot sourcing a ps1 file. By the way, the list had 62 items.

As an alternative I could use Get-Command which would get rid of any filters

Know that this will search for functions in modules not currently loaded so it takes a bit longer to run. This gave me 61 items.

But now at least I can go through the list and identify functions that I haven’t used in years or are now obsolete. Unfortunately, there’s no way to tell from the Function PSDrive or with Get-Command where the function came from.   Luckily I keep all my files in a single drive and most likely the function will be defined in a .ps1 script. I can use Select-String to find it.

In my list there is a function called Show-Balloon that I probably haven’t used in years. What file is it in?

I’m wrapping the function name in a regular expression word boundary so that I don’t get a match on something like show-balloontip. The –List parameter gives me the first match which is all I really need.

image

Because I write all of my functions with the same format, I could have searched like this and gotten the same result.

The output from Select-String is an object which includes a property for the filename or path.

image

Now I can put it all together.

I don’t want to have to re-list all the script files for every function, so I’ll get it once and then use that variable in the Select-Object expression.

image

With this information I can modify my PowerShell profiles and remove the lines that are loading the functions I don’t want or edit the source file to comment out the function if there was something else in the same file I did want to keep.  Any function in this list without a matching source is most likely defined directly in the profile script or will require a manual search.

Time now for a little housekeeping, although I’d love to hear how you keep things tidy in your PowerShell world.

Advice, solutions, tips and more for the lonely Windows administrator with too much to do and not enough time.