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!

 

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.

Using PowerShell to Register MOC VMs

A few weeks ago my friend Telmo blogged about a very elegant solution for handling the VMs that MOC courses use. I was really impressed with what he came up with.  If you are an MCT then I would definitely recommend reading that post. Thanks Telmo!

You can find it here: http://telmosampaio.wordpress.com/2013/09/01/bulk-import-vms-for-moc-classes

That made me think about some simpler scripts that I have written that may also be of use for registering VMs for any environment. I did make some tweaks to use it specifically for registering MOC VMs, but these scripts are easily portable for any environment where you want or need to bulk import VMs.

The code below gives you a script that will do two main tasks:

1. Create some standardized private virtual switches in Hyper-V. The names match the names that the vast majority of MOC VMs use. So there are more switches in there than you would likely need, but it is easily adjusted to modify the name and number of switches being created.

2. Enumerate and import all the VMs that are found in a given path. For this to work you need to feed the name of the parent folder path where all of the VMs reside. If you forget to specify a path when you run the script, there is a basic inline help that is triggered explaining the syntax.
I put a 5 second delay between each import. I have found that if I don’t then I sometimes get strange errors on the VM imports. It feels like the script is running faster than the Hyper-V administration services can process the requests. When I put in a 5 second delay, that problem basically disappears.

I’ve put the code in here twice, one version for Windows 2008 (& R2) Hyper-V servers and a version that will run on Windows Server 2012.

Windows Server 2008 Hyper-V
(requires that the Hyper-V PowerShell module from codeplex has been installed. I didn’t get fancy by doing a check, I just load it up in the first line.)

import-module HyperV
If (!$args){
” “
“Usage of the script is as follows:”
“<path>\importvm.ps1 <VM parent folder>”
” “
“<VM Parent folder> is the path to the directory that holds the Hyper-V virtual machine directories.”
“This script will automatically register all VMs that are in that path and create two private virtual switches if required.”
}
else{
#Create the private network switches
“Create the ‘Private Network’ and ‘Private Network 2’ virtual switches if required”
$switchlist = get-vmswitch | where {$_.Name -ilike “Private Network*”}
If (!$switchlist){
new-vmprivateswitch “Private Network”
“Private Network has been created.”
new-vmprivateswitch “Private Network 2”
“Private Network 2 has been created”
new-vmprivateswitch “Private Network A”
“Private Network Ahas been created.”
new-vmprivateswitch “Private Network B”
“Private Network B has been created”
}
else{
“Private Network switches may already exist. Confirm that the one you require is in the list below.”
“If it is not, you may need to create it manually.”
$switchlist
}
#List the folders in the Drives directory for the course and map them to an array.
$vms = get-childitem $args | where {$_.mode -eq “d—-“}
#Parse the array and import each VM
foreach ($vm in $vms){
import-vm -path $vm.FullName
start-sleep -Seconds 5
}
get-vm | format-table Name,State,Status -AutoSize

}

Windows Server 2012

If (!$args)
{
” “
“Usage of the script is as follows:”
“<path>\importvm.ps1 <VM parent folder>”
” “
“<VM Parent folder> is the path to the directory that holds the Hyper-V virtual machine directories.”
“This script will automatically register all VMs that are in that path and create two private virtual switches if required.”
}
 
else
{
#Create the private network switches
“Create the Microsoft Learning virtual switches if required”
$switchlist = get-vmswitch -SwitchType Private | where {$_.Name -ilike “Private Network*”}
If (!$switchlist)
{
new-vmswitch “Private Network” -SwitchType Private
“Private Network has been created.”
new-vmswitch “Private Network 2” -SwitchType Private
“Private Network 2 has been created.”
new-vmswitch “Private Network A” -SwitchType Private
“Private Network A has been created.”
new-vmswitch “Private Network B” -SwitchType Private
“Private Network B has been created.”
}
else
{
“Private Network switches may already exist. Confirm that the one you require is in the list below.”
“If it is not, you may need to create it manually.”
$switchlist
}
#List the folders in the Drives directory for the course and map them to an array.
$vms = Get-ChildItem $args -Recurse | where Name -ilike “*.exp”
 
#Parse the array and import each VM
foreach ($vm in $vms)
{
“`nImporting {0}” -f $VM.FullName
import-vm -path $vm.FullName
start-sleep -Seconds 5
}
 
get-vm | format-table Name,State,Status -AutoSize
 
 
}
 

Hopefully, this will get you started down the path to scripting more of your common Hyper-V tasks.

Cheers,

James

Enabling Data Dedup in Windows 8

I run a lot of Hyper-V VMs on my Windows 8 laptop, and my second hard drive is getting full, with all of my inactive vhd files.  I was thinking “It’s too bad Windows 8 doesn’t have volume deduplication like Windows Server 2012.” But I decided to have a bit of a nosy around the internet to see if there was a 3rd party solution.

Lo and behold! (And really, it shouldn’t surprise me by now, but it did a little bit anyway.) I found a really useful site that taught me how to hack the 2012 Dedup into my Win8 laptop.

NOTE: Doing this will put your computer in an unsupported state (due to mixing and matching SKUs of the windows code). It is up to you to assess the risk/reward equation of these actions.

Here’s the link:

http://www.scconfigmgr.com/2013/04/13/enable-deduplication-for-your-lab-environment-in-windows-8/

One of the dism commands is a little hard to copy/paste from his website, so here it is:

dism /online /add-package /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab

And since there is no gui for dedup in Windows 8, here’s a link to the online PowerShell help for the dedup cmdlets:

http://technet.microsoft.com/en-us/library/hh848450.aspx

Adding the Lync Import-CsRgsConfiguration and Export-CSRgsConfiguration cmdlets to your Lync Management Shell

Sorry I missed a week. L I’ll make up for it with multiple posts this week. I promise.

First post isn’t a major topic, but it does address a minor annoyance of mine: having to run a PowerShell script to add the Import-CSRgsConfiguration and Export-CSRgsConfiguration cmdlets. When I fire up the Lync 2010 Management Shell, I want all the cmdlets I need available to me.

So here’s the fix:

  1. If you haven’t already done so, download and install the Lync 2010 Resource Kit tools. Assuming that you likely have put them on a Lync server (and in the default location), you should have a folder C:\Program Files\Microsoft Lync Server 2010\Reskit.
  2. From that folder, find the PowerShell script that adds the Response Group Service import and export cmdlets. It is cleverly named RgsImportExport.ps1. Copy that file.
  3. Navigate to the Lync Management Shell module directory, C:\Program Files\Common Files\Microsoft Lync Server 2010\Modules\Lync. Paste the RgsImportExport.ps1 file into that folder.
  4. In that same directory there should be a file named Lync.psd1. Find that file and open it for editing.
  5. Find the “Nested Modules” line and add ,”RgsImportExport.ps1″ to the end of that line. When finished the line should look like this:
    NestedModules=”Microsoft.Rtc.Management”,”Microsoft.Rtc.Rgs.Management”,”init.ps1″,”RgsImportExport.ps1″
  6. Save the changes and close the file.
  7. From here on out, when you open the Lync Management Shell on the computer to which you’ve done this, the Import-CSRgsConfiguration and Export-CSRgsConfiguration cmdlets should be loaded and at your disposal.

One thing to note, if you want the cmdlets available on multiple Lync servers you will need to do the steps above on each server.