Learn How to Create Custom Column Heads for PowerShell Out-GridView

One of my co-workers, who shall remain nameless (but it rhymes with Jalcolm Meffrey), asked a good question today-namely “How do I take this custom formatting from a “Format-Table” command and use it in the gridview control (Out-GridView). It took me a couple of minutes, but the internet bestowed her bounties upon me once again. And, no I’m not talking about going to the hoochie-mama sites.

I found this old posting from Ed Wilson, “The Scripting Guy”. Thank you Ed!

Learn How to Create Custom Column Heads for PowerShell Out-GridView – Hey, Scripting Guy! Blog – Site Home – TechNet Blogs.

For those of you who won’t/can’t be bothered to read it, basically it boiled down to “Don’t use format-table, use select-object, and build your columns using the -f operator syntax”.

With some minor modifications, you turn this:

Get-CimInstance -ClassName Win32_LogicalDisk  |
Where-Object DriveType -eq 3 |
Format-Table @{n=’DriveLetter’;e={$PSItem.DeviceID}},
             @{n=’FreeSpace(GB)’;e={$PSItem.FreeSpace / 1GB};formatString=’N2′},
             @{n=’Size(GB)’;e={$PSItem.Size / 1GB};formatString=’N2′},
             @{n=’Type’;e={$PSItem.Description};width=5} -AutoSize

Into this:

Get-CimInstance -ClassName Win32_LogicalDisk  |
Where-Object DriveType -eq 3 |
Select-Object -Property @{Label=’DriveLetter’;Expression={$PSItem.DeviceID}},
    @{Label=’FreeSpace(GB)’;Expression={“{0:N2}” -f ($PSItem.FreeSpace / 1GB)}},
    @{Label=’Size(GB)’;Expression={“{0:N2}” -f ($PSItem.Size / 1GB)}},
    @{Label=’Type’;Expression={$PSItem.Description}} |  Sort-object ‘FreeSpace(GB)’ | Out-Gridview

 

If you were so inclined, you could swap out “Out-Gridview” for “Format-Table” or whichever output command you needed.

Thanks Jalcolm (if that is your real name) for giving me something to dig into and solve!

 

Advertisements

PowerShell Pitfalls for Managing Multiple Azure Accounts

Or PPMMAA for short . . .

Many (Most?) of the PowerShell and scripting examples for Azure management via PowerShell start with a command sequence that looks like either this:

Add-AzureAccount

Or this:

Get-AzurePublishSettingsFile
Import-AzurePublishSettingsFile

In either case, when you are finished and you run

Get-AzureSubscription

You get a result set that looks like this:
AzureSubscriptions

If you look closely at the output you’ll notice that in addition to the expected properties for each subscription, like “SubscriptionName” and “SubscriptionId” there are two unloved little properties near the bottom of the list for each subscription “IsCurrent” and “IsDefault”. These two are important to use when are using the Microsoft Azure PowerShell console for Azure Management.

Basically, anytime you run an Azure management cmdlet, unless it has a switch that allows you to manually set an account or subscription to run against, ANNNNNDDDDD you happen to use that switch to specify a subscription, any cmdlet you run will execute against the current subscription, i.e. the one that has “IsCurrent: True”. By default, the subscription that has the “IsDefault” property equal to “True” will be the current account. (Funny how that works out, eh?). Which is all well and groovy if you happen to be managing VMs, networks and services in that subscription.

But James, what if I don’t want to manage that subscription? I need to manage one of the others. What shall I do?

Fortunately, we have the means to change the current and default subscriptions. And it is fairly easy to do.

The basic syntax to change the focus to a particular subscription is as follows:

Select-AzureSubscription -Name <SubscriptionName> -Current

The focus for your Azure cmdlets will now be on that subscription until you change it by using the Select-AzureSubscription or until you close the PowerShell console you’re working in. A new console will load up the default subscription as the focus

If you would like a particular subscription to be one that is the defaults in the future, it would be this:

Select-AzureSubscription -Name <SubscriptionName> -Default

After you have ran these cmdlets, run the Get-AzureSubscription cmdlet again to verify that the subscription you identified has now been set as either the current or default subscription. Once it is you are now free to go ahead and manage away!

 

How to get the latest OS image in your Azure deployment scripts

Get-AzureVMImage | where-object { $_.Label -like "Windows*" } | where { $_.Location.Split(";") -contains "West US"} | Sort-Object -Property PublishedDate | Format-List PublishedDate, Label, ImageName

 

via How to make sure you always have the latest OS image in your Azure deployment scripts – The Windows HPC Team Blog – Site Home – TechNet Blogs. This is a trap for new players that can have you pulling your hair out!

 

UPDATE!

Here’s a slightly different bit of code, especially helpful if you happen to know the OS you want.  This makes it a re-usable function, so for a complex script that needed to create multiple VMs, you could call this as needed, adjusting for what OS you needed each time. In the example below, the function is called to populate a variable, $winimage, that would be used somewhere else in the script to create an Azure VM.

function getLatestVMImage($imageFamily)
{
    $images = Get-AzureVMImage |
    where { $_.ImageFamily -eq $imageFamily } |
    Sort-Object -Descending -Property PublishedDate
    $latestImage = $images[0].ImageName
    return $latestimage
}

$winimage = getLatestVMImage(“Windows Server 2012 Datacenter”)

Very Slick! Thank you Enrique Lima for sending this around.

Managing PowerShell 3.0 Updateable Help

***Author’s Note:  I was in a rush and didn’t properly preview the graphics for this post in my browser. If you are finding them hard to read, try using your browser’s zoom-in capability. I found that if I zoomed in a bit, the text in the graphics became legible.  Sorry. :(***

Updateable Help is one of the new features of PowerShell 3.0. The biggest benefit of Updateable Help is the improved accuracy of the inline help, especially across patches/service packs/module additions. While I have to admit that the inconsistencies that would creep in were not a major issue for me personally, I can see how it would create frustration. So we’re going to look at some of the basics of using and managing help for PowerShell 3.0

Using Help

First first—I’m going to assume that if you’re reading this blog that you don’t me to tell you how to get help for PowerShell cmdlets. But you will notice that if you have a computer that has not gotten updated help (and out of the box, it won’t have), you’ll see that a normal Get-Help cmdlet will return the basic list of switches.

You’ll also notice that in the Remarks Section it tells you that the full help has not been downloaded. When you add the –Detailed switch to your Get-help command, the results are not much different. Each switch gets its own line, but the detail you are likely looking for is not there. Again, the Remarks section is telling you to get the updated help. Obviously, getting the updated help is a valid option, but not the only option.

There is a new switch for Get-Help, -Online. Assuming that the computer from which you are running powershell has an internet connection, this allows you to get the detailed help you need, without forcing a full update of the help files. It will open a web browser session and take you to the TechNet Library page for the help for the cmdlet you indicated.

Getting the Help onto Your Machine

That might be fine for module-specific cmdlets that I don’t use often, or while tweaking a script on a server (as opposed to writing a script in whatever environment you normally use), where you don’t really need the help there all the time. However, on the machine that you DO want the help at hand more readily you really want the help files on your machine. Microsoft has provided Update-Help for this.

For the help to update properly I’ve found that I need to make sure I am running the PowerShell console under the Administrator User Account Control (right-click, Run As Administrator).

Once I’ve done that, then I can keep it really simple with the cmdlet Update-Help

If you look at my results you’ll notice a couple of things.

  1. I didn’t run this with the appropriate UAC so some of the help files didn’t update. Easily fixed. Open a PowerShell Console in the correct context and that goes away.
  2. There were a couple of other errors about DTD files and incorrect URIs. Those have to do with the help files not being available properly from the Microsoft servers. Instances of those errors should drop over time. If you want a detailed explanation of what exactly is happening, read this: http://bit.ly/SoMnIB . It explains it all quite well. So we’ll ignore those for the moment.

There are additional switches for the Update-Help cmdlet that allow you more control over what is going on. For instance, the –Module switch allows you to update the help only for a specific module. Take the time to explore those switches and see which ones may be of use to you.

How Do I Update Help if my server doesn’t have access to the Internet?

That was the first question that popped into my head when I first came across this idea of Updateable Help. The solution is reasonably straightforward and done in four steps.

  1. From a machine with internet access (and the appropriate modules you want the help for) run Update-Help.
  2. From the same machine run the Save-Help cmdlet. Save-Help will copy the help files to a directory of your choosing. Much like Update-Help, you can use a –Module switch to only save the help files for a specific module. The main parameter you need to provide is the parent directory where you want the files saved. In the example below I only saved the help for the Hyper-V module.
  3. Somehow transport the directory with all the help files to the computer(s) that don’t have internet access. Network share, portable drive of some sort, whatever works for you really.
  4. On the isolated machine, run Update-Help –SourcePath <path to folder that holds the help files> -Module <Name(s) of modules that have help files in that directory>

You can see in the screen shot below how steps 1-3 work. You will notice that I created a folder to hold the help files, and then ran Save-Help only for the Hyper-V module (for the sake of simplicity). I then displayed what files were put in the destination path.

  1. Once I had done that I can transfer the .cab and .xml files to the remote machine. In this instance I created a folder called “HyperVHelp” on the destination machine and put the files that folder. Once I had done that I ran Update-help. You will note that I used the –Module switch to keep it simple. Had I not done that, my screen would have been filled with red as it tried and failed to update the help for all known modules. The Hyper-V help would still update, but all the error messages are a bit off-putting. So I only updated the module I had help files for.

I ran the Update-Help command a second time, just to show you what can happen if I try to update help files that are currently up-to-date. As you can see, nothing major happens, so there’s no big concerns in that space.

Review

As you can see, the process for updating and managing PowerShell’s help is not terribly difficult. With a bit of practice and planning you should be able to develop and implement a plan for keeping your PowerShell inline help current and useful.

PowerShell 3.0 Workflow Basics

There are lots of new features and functionality in PowerShell 3.0, a brief overview of them found here: http://technet.microsoft.com/en-us/library/hh857339

One of the features that I find most exciting is the new scripting construct, Workflow. If you are familiar with creating a custom Function in PowerShell, then you know most of what you need to know about creating a workflow.

So what’s the difference?  The difference is that when you creating a new command using “Workflow” instead of “Function” in a script, the new command has access to a built-in library of common management parameters, such as PSComputerName, which enable multi-computer management scenarios.  This will make your scripts more powerful, and can be developed in a much simpler fashion.

Below you can see a very basic Workflow that I’ve created and saved on a member server in a domain.

As you can see, the Workflow itself is very basic, doing nothing more than gathering information about the powershell environment and writing it out to a text file that will site on the root of the C: drive. In reality this would need a lot more work, as it assumes that PowerShell is running, which is not a safe assumption if you’re getting this to execute on remote machines.  But ignore that, and assume that you do have a powershell console open on your remote machine.

I could have done the exact same thing with “Function” and it would work just fine on the local machine in which I ran the script.

However,  a look at the help for Get-PowerInfo reveals a host of parameters that are built in to the workflow.

Of immediate interest is -PSComputerName.  This parameter allows the code to run on remote machines (running PowerShell 3.0 and w/ remoting enabled) without me having to specifically add code to the workflow to manage remote sessions or import modules etc.

You can see that my workflow executes successfully, and when I go look at the C: drive on jfin-dc, the output text file has been created.

Obviously, a very simple use (and not all that practical in an of itself), but hopefully you can see that there is a great deal of power in this new Workflow construct in PowerShell 3.0.  As a scripting administrator, I can see how this will make my remote management scripts more powerful and easier to write.