Archive for the ‘Powershell’ Category

Getting Admin’s to adopt PowerShell

October 6, 2008

The RTM of PowerShell was released over 2 years ago. But still there are multiple occasions in which I find myself trying to convince someone that they should really start looking into using this incredible new tool but they end up fighting me pretty hard. There have been a couple consistent themes that I have detected in these conversations that I think are very valid points.

First, I would like to point out that my role at work is a System Engineer. I am not the Operations guy down in the trenches with Ninjas on fire chasing me everywhere I go. My role on the Infrastructure team is to figure out how to incorporate new technology into our existing infrastructure without breaking stuff. I also help troubleshoot issues that get escalated to our team. So suffice to say, I am not an Admin. But, here is some feedback I have gotten from our Ops team members.

The first is that Admins are never going to use something unless they need to. Necessity is the mother of invention, or innovation for that matter. Why would anyone switch from something that works to something that may work but they don’t know how to  use yet? I think the PowerShell team is working very hard to address this very issue, although I think sometimes we miss it in the background when we are introducing people to PowerShell. One of the beauties of PowerShell is that it is a solid consistent language that can be used across multiple technologies. Regardless of whether you are administering an Exchange server or Virtual Machine manager, you are going to likely be doing a “get-doohickey | set-Doohickey.” Also there is tremendous power in the consistency of naming parameters and arguments. All Cmdlets are verb-noun -parameter argument.

I think what the Admin is thinking is that PowerShell is just one more thing to learn. We are having a hard time telling them that the investment they make in learning PowerShell to manage Exchange will also help them with VMM, desktop management, AD,Group Policy, and Terminal Services, just to name a few.

The second issue is really a two-edged a sword. There is an awesome community supporting PowerShell and a ton of great content on the web that has been worked on over the years and is really quite mature. The problem here is that newcomers to PowerShell start seeing some of this stuff and get completely overwhelmed right away. If a complete beginner asks “How can I filter the services to see just the ones that are stopped?” and they find something like gsv | ? {$_.status -eq “Stopped”}” they will completely freak out. On the other hand, they may use it but not understand what is going on and just save it as another tool in their tool bag, without understanding that they can filter just as easily on processes or on Virtual Machines.


There is one thing that I believe has not been sold quite as much as necessary is Tab-Completion. Take the example below copied from a blog entry from the MS Exchange Team

This is the Exchange Management Shell (EMS) command Tom would enter to generate the cert request to be provided to the 3rd party CA in order to generate the actual certificate:

New-Exchangecertificate -domainname,, contoso.local,, server01.contoso.local, server01 -Friendlyname contosoinc -generaterequest:$true -keysize 1024 -path c:\certrequest.req -privatekeyexportable:$true –subjectname “c=US o=contoso inc,”

We have found that the ‘–subjectname’ option is the most confusing. The help contents in EMS are vague as well. The best description is found in the TLS whitepaper mentioned at the beginning of this post so we’re not going to reproduce it here.


As an admin I would look at this and say something like, “Crap, who created this huge long command line entry. Editing this is going to suck.” What people don’t get is that they have Tab Completion available, not just for the Cmdlets but for parameters as well. This just doesn’t get conveyed when we are posting examples. Now if you throw in PowerTab or Intellisense from PowerShell Plus, its just gravy.

And so, I would like to pose the question to you, how do you as an engineer or an admin get your teammates to start using PowerShell. What walls have you come up against and what can we as a community to do to help break down these walls.

One thing I have been doing lately is using PowerShell in the build guides and Ops guide that I write, to at least get people started with using it. What else can we do?


Using Consolas in PowerShell Plus on a 64 bit machine

September 26, 2008

I love the Consolas Font for code. I spent a while trying to get PowerShell Plus to use the font in the interactive console. I noticed that when I went to save my settings I got a Console Settings windows just like the console for CMD and PowerShell out of the box.

It kept going back to Lucida Console.  I added consolas with the PS Plus Add font utility but that didn’t do the trick on my 64 bit machine.

I found this article on Scott Hanselman’s Blog and it seemed to do the trick.

Add a REG_SZ with name 00 and value Consolas to HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont

Note that you need to reboot.

PowerShell Plus 2.0 Ships!

September 25, 2008

The great folks over at Idera have released PowerShell Plus Professional 2.0. Once you use it, you’ll never go back to cmd.

Plus (no pun intended) they have support for C#, VB, and a great XML editor.

Go and get a free 14 day trial now and use the 2 weeks to find a way to convince your boss that it is worth so much more than the $79.00 price tag.


The $79 price tag goes up to $145 on October 1st.  but you still have a week to sell it to your boss !

Roles and Features Part 2

September 18, 2008

I have been playing with a tool called servermanagercmd which is a commandline tool which functions like ServerManager. It allows you to install different Roles, Features, and Role Services in Windows Server 2008. I mentioned in an earlier post that you can output it to an XML file and use Powershell to look at what is installed.

There is an -inputpath parameter that takes an answer.xml file. You would think that you could go to one server, do a servermanagercmd -query role.xml and then take that file to another server and do a servermananagercmd -inputpath role.xml and it would install all the roles and services that were on the original server. Yeah.. that would be nice, but no such luck. They are two different XML Schemas that apparently have nothing to do with one another.


To further complicate the issue, servermangercmd is used in the full version of Windows 2008. But what if you wanted to install or remove roles in Windows 2008 Core. Forget servermanagercmd, its not there. Instead you have to use two different commands, ocsetup and oclist. OC standing for “Optional Component” ?

oclist in Core is the same as servermanagercmd -query

ocsetup is servermanagercmd -install

To screw things up even more, the aliases for the roles are not even the same between the two tools. Just an example, in the full version with servermanagercmd you add the feature called Failover-Clustering. In core, you use ocsetup to install FailoverCluster-Core.

Completely inconsistent, no intuitive, and unnecessarily complex.


Perhaps what would be cool is a PowerShell function that could at least convert the output of servermanagercmd -query query.xml and turn it into an xml file that could be used by servermanagercmd -input input.xml. Any PowerShell XML Ninjas up for the challenge ?


Viewing Roles and Features with PowerShell

September 8, 2008

I am in the process of deploying a fairly large TS Server Farm with Windows Server 2008. You probably know that in 2008, you have roles and features that can be added to the Operating System. In fact, PowerShell shows up as a feature in 2008.

All of these roles and features are managed through an MMC called ServerManager. It’s fairly intuitive to add or remove roles and features using this tool. There is also a command line version called servermanagercmd.

I just started playing with this and you can use servermanagercmd to install or remove roles, and you can also use it to query what is installed. The cool thing about the query feature is that it can dump it to an XML file.

So check this out

   1: servermanagercmd -q rolesandfeatures.xml
   2: $xml = [xml](gc rolesandfeatures.xml)
   3: $roles = $xml.get_documentelement()
   4: $roles
   5: $roles.role
   6: $roles.role | ? {$_.Installed -eq "true"} | ft DisplayName
   8: DisplayName
   9: -----------
  10: Terminal Services
  11: Web Server (IIS)


Their is also input functionality built into the tool and I am sure that this is reversible. I’ll keep you posted on how that goes.




September 7, 2008

I recently had the need to be able to create a VM on a few of our Hyper-V servers at work. I found a great article by The Virtual PC Guy on how to create a new VM. I took what he had and extended the functionality a bit. To manage Hyper-V, for now, we are pretty much stuck with WMI. However, Virtual Machine Manager will help us out a bunch. In the meantime, we can start with WMI. I figured it never hurts to know what is going on under the hood anyway.

One key piece of functionality that was not included was the ability to override the default location for new VM’s when they are created. This is critical to us as we are using a SAN and have dedicated LUN’s for our clustered VM’s. So now that you have the background, here’s the code

   1: function New-HyperVVM {
   2:     param    (
   3:             [string]$Hypervhost = "localhost",
   4:             [string]$Vm = "VM Courtesy of PowerShell",
   5:             [string]$location = "C:\MyVirtualMachines\$vm"
   6:             )
   7:     $wmiClassString = "\\" + $Hypervhost + "\root\virtualization:Msvm_VirtualSystemGlobalSettingData"
   8:     $wmiclass = [WMIClass]$wmiClassString
   9:     $newVSGlobalSettingData = $wmiClass.CreateInstance()
  10:     $newVSGlobalSettingData.psbase.Properties.Item("ExternalDataRoot").value = $location
  11:     $newVSGlobalSettingData.psbase.Properties.Item("ElementName").value = $Vm
  12:     $VSManagementService = gwmi MSVM_VirtualSystemManagementService -namespace "root\virtualization" -ComputerName $Hypervhost
  13:     $GlobalSettings  = $newVSGlobalSettingData.psbase.GetText(1)
  14:     $VSManagementService.DefineVirtualSystem($GlobalSettings, $ResourceSettings)
  15: }

By the way, this is posted up at PoshCode. I highly recommend getting the code from their, and updating it !

Start Posting to – NOW !!!

August 18, 2008

Hal posted a comment a while back asking if I would consider putting some of the functions i had been blogging about up on I had heard of it and even used some of the scripts up there but for whatever reason I hadn’t bothered to post anything. Hal finally convinced me to put some code up there. I have to say, its ridiculously easy.

My 0.02 is this should be the default shared online repository for Powershell scripts and functions. So I have one question for you.. Why are you still reading this and not posting your latest and greatest script up to PoshCode?

Go and do it.. now !



August 17, 2008


   1: PS C:\> Get-GreatestSwimmerEver
   4: NumberGoldMedalsIn2008    : 8
   5: NumberWorldRecordsIn2008  : 7
   6: LifetimeOlympicGoldMedals : 14
   7: FirstName                 : Michael
   8: LastName                  : Phelps
   9: GreatestSwimmerEver       : True
  13: PS C:\>

A thank you note from an intern

August 15, 2008

We had several high school students working for us this summer as interns. It was a great experience. I just had to share a section of a thank you note I received from one of them the day they completed their internship.

"I thought it would never be possible for me like coding again, after a year of programming class. But after a week of PowerShell, I liked coding again .. but only in PowerShell !!"

I love the fact that Powershell helped me get a high school student interested in scripting, and that it is quite literally "Changing the world one line at a time."

PowerShell Function Set-NetInterfaceName

August 13, 2008

Now that you are able to set an IP address given a name of a network interface, you may want to change that name.

Here’s a quick little function to do that.

   1: function Set-InterfaceName {
   2:         param(  
   3:                 [string]$oldName,
   4:                 [string]$newName
   5:          )
   7:         $NicInterfaceName = gwmi Win32_NetworkAdapter | where {$_.netconnectionid -eq $oldName}
   8:         $NicInterfaceName.netconnectionid = $newName
   9:         $NicInterfaceName.put()
  11: }