rickgaribay.net

Space shuttles aren't built for rocket scientists, they're built for astronauts. The goal isn't the ship, its the moon.
posts - 303, comments - 180, trackbacks - 35

My Links

News

Where's Rick?


AgileAlliance deliver:Agile 2019- 4/29
Desert Code Camp, PHX - 10/11
VS Live Austin, TX - 6/3
VS Live SF - 6/17


About Me
Hands on leader, developer, architect specializing in the design and delivery of distributed systems in lean, agile environments with an emphasis in continuous improvement across people, process and technology. Speaker and published author with 18 years' experience leading the delivery of large and/or complex, high-impact distributed solutions in Retail, Intelligent Transportation, and Gaming & Hospitality.

I'm currently a Principal Engineer at Amazon, within the North America Consumer organization leading our global listings strategy that enable bulk and non-bulk listing experiences for our WW Selling Partners via apps, devices and APIs.

Full bio

Note: All postings on this site are my own and don’t necessarily represent the views of my employer.



Check out my publications on Amazon Kindle!





Archives

Post Categories

Published Works

Using PowerShell to Manage Network Interfaces and Windows Services

PowerShell is a new scripting language that allows you to interact with applications, services and objects as objects. It is a .NET application which shells commands out on your behalf. This is very powerful, because it allows you to leverage the strengths of an object oriented model within your scripting tasks with a very terse, yet simple scripting language. Because it is written in .NET, you can access .NET types, objects and WMI objects from a command prompt.

My current workstation runs Windows Server 2008 Standard Edition with Hyper-V. I use the host/parent partition as my office, and have a number of child partitions that are integrated into a Windows Server 2008 Domain. Needless to say, this configuration gives me everything I need to develop, test and integrate multiple Server OS', platforms and technologies, and is my environment of choice for developing production code. It still amazes me how far we've come in such a short period of time. Not too long ago, I remember setting up similar lab environments at home running Windows NT 4 and Windows Server 2000 on dedicated physical machines.

Anyway, I have to say that I am absolutely delighted with my environment, but it took me some time and effort to learn how to tune Server 2008, and this is all well documented in previous posts. One of the the things that I do to keep performance high is that I only have the 3 services required for Hyper-V running when I need them. In other words, if I am only working with email and writing documents or design drawings, I don't need to have the Hyper-V services running because they are resource intensive. In addition, I only want my loopback adapter (that provides me with a virtual LAN for all of the child partitions on my domain to communicate) enabled when I need it to be. One reason for this, is that if I leave my loopback on and reboot, boot times can take up to 10 minutes because the loopback is configured to use my domain controller as the primary DNS server, which is a VM. Because the DNS Server only runs when my Domain Controller VM  is up and running, the VM will only come up when I start it. As a result, Windows tries and tries to reach the DNS server for the Loopback adapter until it finally gives up (If anyone knows how to change this timeout, please shoot me a note or post a comment).

So, I only want Hyper-V services running when I need to work in my development environment, and I don't want my loopback enabled unless it needs to be. For a while, I was managing this as follows...

First, I set the following services to "Manual", so that they do not start automatically:

  • vmms: Hyper-V Virtual Machine Management
  • vhdsvc: Hyper-V Image Management Service
  • nvspwmi: Hyper-V Networking Management Service

The service names are a bit obscure, but the "friendly" names are pretty self explanatory. When I need to start my development environment, I would go into Server Manager, and start each service one by one.

Next, I would enable my loopback adapter so that my child partitions can communicate with each other.

All together, this resulted in a number of clicks, which was somewhat mundane to do every time. Worse, once I enabled the loopback, I often would forget to disable it before shutting down (remember, servers running Hyper-V do not support hibernation). For a while, I thought about writing myself a sticky note and posting it to my forehead so that I would not forget to disable the loopback, and finally, I decided to create an easy button for starting and stopping my development environment.

This is where Powershell comes in.

Using PowerShell to Query and Manage Network Adapters

The first thing I did was figure out how to talk to my network adapters so that I could enable and disable my loopback as needed. It turns out that Microsoft provides a WMI object called Win32_NetworkAdapter. The object exposes a bunch of properties for working with an instance of a Win32_NetworkAdapter:

image

In addition, there are 4 public methods that are exposed, and well documented as shown below:

image

To enumerate all network adapters on my host/parent partition, I issued the following command:

   1: Get-wmiobject win32_NetworkAdapter | format-table 

PowerShell lists each adapter and certain properties in a tabular format because I added a pipe and format-table parameter:

image

To identify the instance that corresponds to my loopback, I simply need to find the "Internal VLAN" instance above, which has a DeviceID of 17:

image

Next, I want to retrieve an instance of the adapter with a DeviceId of 17, so I issue the following statement:

   1: Get-WmiObject win32_networkadapter | where {$_.DeviceId -eq 17}

The where keyword uses a bracketed expression to evaluate the condition. The "$" is a temporary variable, which is similar to the "this" keyword in C#, which provides context for the current instance. The "-eq" operator is the equality operator in PowerShell. So, we are querying all adapters for the adapter with a DeviceID equal to 17. The above command returns the following:

image

Notice that each property is an actual documented property of the WIN32_NetworkAdapter object. If we have access to properties, it would be helpful to determine if the adapter is enabled or disabled. To do this, I assign the adapter to a variable called $adapter as shown below, and then I get the value of the Availability property:

image

The value of the Availability property is 3. Referring to the WIN32_NetworkAdapter documentation, I can see that a status of 3 indicates that adapter is on, and running on full power.

image

Are you getting the hang of it yet? Hopefully, the interaction with PowerShell should feel object-oriented because it is! We are getting a reference to the WMI shell of the adapter and then using it's get accessors to get the value of the public properties. So, if we can get a reference to the adapter, get properties, we should be able to call methods on it, right?

To disable the adapter, I simply call the Disable() method on my $adapter variable:

image

Now, to confirm that the adapter is disabled, you can look at Network Connections and you will see that the Status is in fact Disabled. To do this programmatically via PowerShell, you can use the ConfigManagerErrorCode property which is also documented. Get a new instance of the adapter, and call the ConfigManagerErrorCode property on it as shown below:

image

A return code of 22 can be matched to the table in the MSDN documentation:

image

Now, enable the adapter by calling the Enable() method:

image

A return code of 0 indicates that the adapter is enabled, and working properly:

image

As you can see, PowerShell is a very easy to use, yet powerful tool for managing system objects in an object-oriented manner. You don't need to worry about writing VBScript or C# to accomplish simple administrative tasks such as enabling and disabling a network adapter. As you might imagine, the real power comes in being able to run a series of PowerShell commands in a batch, perhaps at the click of the button. This is exactly what I'll cover next.

Using PowerShell to Query and Manage Windows Services

You'll recall that I only want the 3 Hyper-V services to run when I need them, so what I want to do is create an "easy button" to toeggle my development environment on and off.

The "On" should:

  • Enable my Internal VLAN Adapter
  • Start the Hyper-V Virtual Machine Management
  • Start the Hyper-V Image Management Service
  • Start the Hyper-V Networking Management Service
  • Get me a cup of Starbucks coffee

The "Off" Button should:

  • Disable my Internal VLAN Adapter
  • Disable the Hyper-V Virtual Machine Management
  • Disable the Hyper-V Image Management Service
  • Disable the Hyper-V Networking Management Service

     

    I've already covered how to manage network adapters using PowerShell as a primer, so I'll jump right into working with Windows Services. As with any program, sometimes it is helpful to group commands into a subroutine. In PowerShell, these functions are referred to as cmdlets (prounounced "commandlets"). You may not realize this, but you've already been working with cmdlets if you've tried the commands I covered above on your own machine. The get-wmiobject command is actually a cmdlet that provides a reference to the WMI object specified as the parameter. You could accomplish this without the cmdlet, but why would you want to?

  • Fortunately, a cmdlet is also available for working with Windows Services: get-service.

    To get information about a particular service, simply call get-service with the service name. The actual service name of the Hyper-V Virtual Machine Management service is "vmms", so issuing the get-service vmms command returns a few properties including the Name, DisplayName and Status of the service.

    image

    Starting and stopping the Hyper-V Virtual Machine Management service is as simple as calling the appropriate method: Stop() to stop the service and Start() to start it. While you could use a variable called $service to store the reference to the service object, an abbreviated way to accomplish this is shown below:

       1: (get-service vmms).Stop()

     

    Now, when you issue the get-service vmms command, you can see that the Status property is "Stopped":

    image

    Starting the service back up is as simple as calling Start() on the cmdlet expression:

    image 

    Building the "Easy Buttons"

    There may very well be a more sophisticated way to do this, but I created two batch files, one called "Start.bat" and the other called "Stop.bat" and placed them in my documents folder. Each file contains the appropriate PowerShell syntax as shown below:

    image

    Note, to re-use variables across PowerShell sessions, you must first configure a PowerShell profile: http://msdn.microsoft.com/en-us/library/bb613488(VS.85).aspx

    Next I created two desktop shortcuts, appropriately named "Start" and "Stop" and set the target to each corresponding file.

    Now, I have two "Easy Buttons" for toggling my development environment on and off. While I can't guarantee that I won't forget to press the "off  button" before shutting down, it is a heck of a lot easier than going through the contortions manually.

    One last note. If anyone finds or builds a cmdlet that runs to Startbucks and picks up a medium drip with 1.5 Sweet & Low and delivers it to my client site, please let me know :-)

  • Print | posted on Friday, September 26, 2008 3:02 PM | Filed Under [ Misc. .NET 3.5 ]

    Feedback

    Gravatar

    # re: Using PowerShell to Manage Network Interfaces and Windows Services

    Any reason you don't just start PowerShell once and send a string like this?
    c:\windows\system32\windowspowershell\v1.0\powershell.exe "$loopback.enable;(get-service vmms).start();(get-service nvspwmi).start();(get-service vhdsvc).start()"

    Just curious. It seems bringing up 4 different instances of the runtime is a bit excessive.
    Good post though, handy info to have.
    10/7/2008 7:32 PM | Jono
    Comments have been closed on this topic.

    Powered by: