Mark Minasi's Windows Networking Tech Page
Issue #102 October 2012

Document copyright 2012 Mark Minasi; please see below for info on subscribing, unsubscribing or copying portions of this text.

What's Inside

  • News
    • Learn with My Seminars, Audio Recordings and More!
  • Tech Section
    • IPConfig Reimagined:  PowerShell Saves an Old Friend
  • Conferences
  • To Subscribe, Unsubscribe, Read Old Newsletters or Change Your Email Address

News

Hi all —

PowerShell's an interesting sort of creature for administrators.  In one sense, it's just another command line environment and an ever-growing collection of separate commands.  But spend a little time with it -- and I do mean a little -- and you can start gluing those commands together to build new tools.  I love that because while I also love the industry we're in, the computer biz does sometimes have a tendency to say "what's that you say, that tool doesn't fit your hand?  Hmmm... well, have you considered surgery?," and that's when I really want to be able to create my stuff that meets my needs.  I got a chance to try that out with Windows 8 and Server 2012's new PowerShell cmdlets recently, and the result was a bit of "IPConfig meets Steve Austin."   I hope you find either the new tool or the knowledge of how I made it useful.  But first, a word from our sponsor...

Don't Miss ITEdge Intersection!

Windows Server 2016 is coming, are you ready? Server 2016 and many other important topics are the focus of ITEdge Intersection at the MGM Grand in Las Vegas, Oct 25-29. Your favorite speakers are there, including Scott Guthrie, Brad Anderson, Jeffrey Snover and of course, Mark Minasi. Register today for the conference and a workshop and you can go home with an XBOX One S, Surface 3 table or MS Band 2. Register at www.itedgeintersection.com.

Bring Mark's Windows 10 Support Class and Our PowerShell Classes to Your Site

Mark has delivered his new "Deploying, Managing and Securing "the Last Windows: Working with Windows 10" class to nearly a dozen clients, and the reviews are uniformly great.  Designed for the Windows 7 support pro, this course tells you everything you need to know to support, deploy, or manage Windows 10 systems.  Fast-paced, lecture-based and entertaining, this course gives you the shortest path to Windows 10 expertise. Learn about Windows 10's completely new licensing approach.  See how to enable the new "parallel universe" security tools.  Discover the cloud-y new tools in Windows 10 like joining a system not to an Active Directory but instead to a cloud.  Find out what you can learn at our course outline at http://www.minasi.com/w10class.htm. 

To bring this class to your site, just drop us a line at assistant@minasi.com.

And while you're at it, are your folks PowerShell adepts?  There really isn't a productivity-enhancer available for Windows support people like PowerShell.  Bring Mark's "Learning PowerShell: Hands-On with AD, Networking, and More" class to your site and he'll make your command-line-hating techies into PowerShell fans.  Outline at http://www.minasi.com/Posh2day/. 

IPConfig Reimagined:  Building a Simple PowerShell Tool

While exploring Windows Server 2012's new PowerShell tools, I got the notion to try my hand at building a PowerShell script to partially replace IPConfig.  Along the way, I learned some things about new 2012 tools and created something at least halfway decent, so you'll soon see how to get it and install that script for your own use.  And as a bonus, there's some extra-for-experts on how I researched and assembled my script "from scratch."

Introduction:  An Old Friend, on His Last Legs

If memory serves me right, this year marks the 20th anniversary of the release of Microsoft's first TCP/IP stack, the "Wolverine" beta for Windows for Workgroups 3.11.  One of the first Wolverine commands I learned was ipconfig, and to paraphrase the closing lines of Casablanca, it was the beginning of a beautiful friendship.  After all these years, however, my old pal is, well, not exactly as much fun to be around as he once was.  Where he once reported on my IP connections concisely, precisely and aptly, of late he's gotten a bit more chatty, nattering on about tunnel adapters that I couldn't give a hoot about, swelling his output to gargantuan levels.  Worse, he won't stop talking about the old days, with constant chatter about NetBIOS, WINS and NetBIOS over TCP.  Between you and me, I'm a bit worried that he may be in the early stages of some sort of dementia, as he actually -- it embarrasses me to reveal this about an old friend, but it's true -- scrolls right off the screen... and quite frequently! 

For the past six years or so, I've been joking to crowds that I wish ipconfig had a "/noBS" switch and I always get a big laugh, so I know I'm not the only one who feels this way.  If only, I've been thinking, there were a way to trim ipconfig /all down to the minimum, modernize it a trifle and spiff my old buddy up a bit.  But whenever I thought about it, the idea of  chasing down all those Registry entries and WMI locations took the wind out of my sails.  "I am definitely going to pull out the C++ compiler and cobble together a new ipconfig," I'd say to myself, "... but it'd be a lot of work, so not today.  One day, though..."

Well, thanks to PowerShell, that one day a couple of Saturdays ago.  I was playing around with Windows Server 2012's five zillion new network-related PowerShell commands.  You can see them for yourself if you're running Windows 8 or Server 2012, and inasmuch as there are trial versions of them free for the downloading, I recommend you give them a try.  Fire up a 2012 system just to run it through its paces and, while you're doing that, open up a PowerShell prompt and type

get-command get-net*

When you do, you'll see no fewer than 69 cmdlets.  Play around with a few of them, as I did that day, and you'd soon find yourself thinking,

"Hey, this stuff's an awful lot of what I'd need.  Ipconfig's in trouble, but...

"We could ... rebuild him.  We have the technology...," and for a whole lot less than six million dollars.

How to find your way through all of those PowerShell network cmdlets?  If we just review a few PowerShell basics then it's not quite so scary.  As I said in my newsletter about how to get things done in PowerShell, recall that PowerShell tries to keep the number of different verbs that it uses in its cmdlets to an absolute minimum, and so if you wanted to see, say, information about your network adapters, you wouldn't look for "show-netadapter,"  "display-netadpater," "list-netadapter," or "enumerate-netadapter" -- nope, if PowerShell knows about something called a "netadapter," the cmdlet to dump them all out had better be get-netadapter.  That soon led me to get-netipaddress, net-route, net-DNSClientServerAddress, and at that point I had a pretty impressive pile of data about my network, network cards, and TCP/IP stacks.  In under four hours time (most of which was research rather than coding), I had a useful, if ugly, prototype.  Four more hours of  pretty-fying, and I had something that didn't look terrible.  I call it "Get-IPInfo," and here's a screen shot:

I aimed at being able to report on three NICs in roughly one page of an average command prompt window, I think, pretty much got there.  Basically, I

  • Ignored all adapters except actual physical NICs.
  • Skipped the NetBIOS/WINS info, routing (RRAS does a better job now), whether or not autoconfiguration is enabled, DHCP lease info (only because I can't find it in any cmdlets or the Registry), and connection-specific DNS suffix.
  • Reported multiple DNS servers and suffixes on one line rather than a server to a line to save space.
  • Packed the adapter name, interface index and status into one line again to save space, and saved a line per NIC by showing the subnet mask as in CIDR "slash" notation, so what was "255.255.255.0" is just "/24."
  • Added interface index, as it's more important nowadays, particularly in some cases with PowerShell cmdlets.
  • Added NIC link speed.

Of course, in reality it's a bit lamer than the real ipconfig in several ways, here are a few caveats:

  • This only runs on Windows 8 or Server 2012.  I'm sure it could be rebuilt to work on Win 7/R2, but again I lacked the time to spelunk through the WMI hierarchy.  I am absolutely sure, however, that any PowerShell "blue belt" could rewrite this thing so it'd work on the earlier Windows.
  • All this does is display information -- it lacks any command-line options or functions like /release, /renew, /registerdns and the like.
  • Many of you would, I'm sure, have chosen a different set of items to display.  That's the beauty of this, though -- it's a PowerShell module, and as the source code follows, you're more than welcome to change it to your needs.

Getting and Installing Get-IPInfo

Assuming my little utility looks interesting, here's how to get, install and run it.  Having said that, I'd imagine that any PowerShell blue belt could write a few get-wmiobject cmdlets and not only duplicate what I've done but significantly improve it. 

Step One:  Copy the Code to Notepad

Copy all of the following text, the 180ish lines of Courier text, from this page to your clipboard:

# Fun clone "reimagining" of ipconfig -- the equivalent of ipconfig /all for three
# NICs and still fits on a screen!

# Copyright 2012 Mark Minasi, but go ahead and use it in any way that you'll find
# helpful or fun... it'd be nice if you'd leave my name in it but otherwise give
# it away, make better tools for yourself and your co-workers, that sort of thing.
# My newsletters, seminars and forum are at http://www.minasi.com


# The stuff between the <# and the #> is help... it's not part of the meat of the program.
# TO INSTALL THIS:
# Create a folder called \WindowsPowerShell\Modules\ifconfig\ in your Documents folder.
# Copy this text, paste it into Notepad, and save it in the ifconfig folder as
# "ifconfig.psm1" and yes, that's right -- the file's name must match the folder
# name.
# Start up PowerShell, type "get-ipinfo," and it'll run.
Function Get-IPInfo {


<#
.SYNOPSIS 
Generates a summary report on your NIC and IP status.

.DESCRIPTION
Get-IPInfo tries to offer output like the venerable ipconfig command, but
in a somewhat more concise fashion, adding a few new bits of information
provided by Windows 8 and 2012's in-the-box cmdlets, including link speed.

.INPUTS
None. Get-IPInfo doesn't take any input parameters, nor does it make use
of pipeline input. And the fact that Help claims that it takes the common
parameters just plain isn't true -- this cmdlet was built by a guy who 
knows very little about PowerShell scripting.

.OUTPUTS
Just text, with hope self explanatory text.

.Link
get-netadapter inventoried the adapters -- just the real ones  -- and
provided NIC name, index, description, link speed, MAC address
and more.

get-netipaddress provided the IP addresses, subnet mask size, 
source (DHCP or manual).

get-netroute provided the default gateways.

get-DNSClientGlobalSetting provided the DNS suffix search path.

get-DNSClientServerAddress provided the DNS servers.

#>


PROCESS {

<#
Collect the old stuff... hostname, suffix info. All pre-.NET so we've got to go to the
Registry for the suffix.
#>

# This command reads the environment variable "COMPUTERNAME=" and stores
# it in a variable I just created called $Hostname. Get-content basically
# retrieves what's in something like an environment variable or a file.
# Name of variables in PowerShell, by the way, always start with a dollar sign.

$Hostname = (Get-Content ENV:Computername)

# Next, get the suffix from the Registry. To do that, we examine the TCPIP/Parameters
# Registry key, using Get-ItemProperty, and that's the roundabout way we've got to do
# in PowerShell to THEN retrieve the value of a Registry entry in that key, "NV Domain."

$PrimaryDNSSuffix = (Get-ItemProperty HKLM:\System\CurrentControlSet\Services\Tcpip\Parameters)."NV Domain"

# The DNS suffix search list is a bit easier, as one of the new PowerShell net-related
# cmdlets contains it. If you were to type "Get-DnsClientGlobalSetting", you'd get 
# several lines of output, including "SuffixSearchList." This syntax lets me capture
# it into a variable I just created called "$DNSSuffixSearchList"

$DNSSuffixSearchList = (Get-DnsClientGlobalSetting).suffixsearchlist

# Time to produce some actual output. Just type the strings that you'd like
# PowerShell to display, and use the plus sign to glue two strings together.

# Write title and NIC section
""
"Windows IP Configuration"
""
" Host Name................: " + $Hostname 
" Primary DNS Suffix.......: "+ $PrimaryDNSSuffix
" DNS Suffix Search List...: " + $DNSSuffixSearchList 

# Next, we'll start gathering information for each NIC. That'll be much easier if
# we have a list of NICs somewhere, so I'll use get-netadapter to get lots of info
# about each NIC, and store all of it in one big variable called $NICs.
# It does it with a new cmdlet called "get-netadapter" that delivers a
# data object for each real physical NIC that you have.

$NICs=get-netadapter

# Now that I've got my bunch of NIC objects in $NICs, I want PowerShell to analyze
# and report on each one at a time, looping from the first to the last.
# 
# The PowerShell command to do that is "foreach." Simply typing
# $NICs
# and pressing Enter would cause PowerShell to dump out everything it knows on 
# the screen, which would be way too chaotic and unrefined, so instead I can 
# use foreach to do the looping for me. Basically foreach looks like
#
# $NICs | foreach {command1; command2; command3...}
#
# Which causes foreach to grab the info on the first NIC and do command1, then 
# command2, and then command3, then get the next NIC and do commands1, 2, and
# 3, and so on. Because I'm going to want to do a lot of things to each NIC
# it'll be more than three commands, AND it'll stretch over a fair number of 
# lines. Watch the "{" and its matching "}" to see the span of commands that
# foreach will do for us, but if you do, notice that we'll end up with TWO
# foreach commands -- one "nested" inside another.
#

$NICs |
foreach { # for each NIC section
# Leave a blank line between what we've written so far and the beginning of 
# the section about this NIC... I want to look at ipconfig-ish as possible.

write ""

# Next, list the adapter's name, its index number and status as its section heading


"Adapter '" + $_.interfacealias + "' Index=" + $_.ifindex + " Status="+$_.status + ":"

# Another blank line, again very ipconfig-ish

""
# And then a series of statistics about this NIC
# They're just properties from this particular NIC's object

" " + "Description ............: " + $_.InterfaceDescription 
" " + "Link Speed..............: " + $_.LinkSpeed
" " + "Physical Address....... : " + $_.MacAddress

# Next, default gateway. In theory every NIC has only one default gateway,
# but get-netadapter does not include that info. Instead, we'll use another
# cmdlet, "get-netroute" and pass it the index number of this NIC, like
# get-netroute -InterfaceIndex 12
# THAT gives us an object that is the routing table for that NIC.
# We then just look for the route whose "NextHop" is "0.0.0.0" -- the address that means
# "the whole world" -- and whatever address it tells us to use to get to
# the whole world is the default gateway.
# The "Where" stuff is where we pluck off JUST the line with the gateway.
# We store that in $defaultgateway. 

$defaultgateway=(get-netroute -InterfaceIndex $_.ifIndex | Where {$_.DestinationPrefix -like "0.0.0.0*"}).NextHop

#Now that we've got it, print it out

" " + "Default Gateway........ : " + $defaultgateway

# Next, use yet another cmdlet, get-DnsClientServerAddress,
# to retrieve the DNS servers associated with the NIC,
# and as we've done before, report them

$dnsservers = (get-dnsclientserveraddress -interfaceindex $_.ifindex).serveraddresses
" " + "DNS Server(s).......... : " + $dnsservers

# There's one more thing we need to know about this NIC... its
# IP address or, more likely nowadays, IP addressES. As we do
# not know how many NICs are there, it's time for another
# foreach, and a cmdlet that will give us an object for each
# IP address on our current NIC. That cmdlet is the get-
# newipaddress. Note again that we're doing a foreach INSIDE
# a foreach.

$ipaddress=get-netipaddress -interfaceindex $_.ifindex 
$ipaddress |foreach {
#grab each IP, collect the ipaddress type, address, the
# CIDR-type subnet mask length and source and report

" "+$_.addressfamily+ " Address........... : " + $_.ipaddress + "/" +$_.PrefixLength
" Source of Address.......: " + $_.SuffixOrigin
}
# Done with that IP address, on to the next address
""
} # Done with that NIC, leave a blank line and on to the next one
} # And now we're done!
}

 

(The text to copy ends on the previous line.)

Now copy that text to Notepad.

Step Two:  Create a Module Folder

This is to be a PowerShell module, and modules have to go into very specific folders.  So please go to your Documents folder and create a sub-folder in it called  WindowsPowerShell\Modules\ifconfig\ and then save the text you just pasted into Notepad as a file named ifconfig.psm1 into that folder.  The file name is important, as it must match the name of the folder -- if a .psm1 file's name is ignatz.psm1, then it had better be in a folder in Documents called \WindowsPowerShell\Modules\ignatz.

Step Three:  Tell PowerShell that It's Okay to Run Scripts

Now fire up PowerShell and type

set-executionpolicy remotesigned

You need to do that because out of the box, PowerShell won't run scripts of any kind.  You've just relaxed its rule a bit to allow scripts that are either written by you locally, or scripts you got from the Internet, provided that those from-the-Internet scripts are digitally signed.  I don't have a code signing certificate and so therefore cannot sign my scripts, which is why I had you copy the text to Notepad and save it to your hard disk -- that makes it look to PowerShell on your computer as if you wrote the code, not me.  (Go ahead, take the credit, I don't mind.)

Step Four:  Fire it Up

At this point, just type "get-ipinfo," press Enter and you should have the magic.

Why Get-IPInfo:  A Nice First PowerShell Scripting Foray

Okay, so why did I bother with this, and why should you care? 

Well, first, it let me demonstrate to myself that I could generate a fairly useful "reimaging" of an old standard by bolting together a bunch of data gathered from a half-dozen PowerShell cmdlets.  I'd never written a nontrivial PowerShell script before -- this is my first PowerShell script that ran more than four lines of code -- and it took me no more than four hours to put the original code together, and a few more to comment it, make it pretty, write some basic documentation and make to ready to be a PowerShell module.  I didn't have to spend days poring over WMI calls.  I didn't have to write a pile of For/Next or Do/While loops.

More importantly, I did this in the hopes of convincing many of my readers -- maybe you! -- that PowerShell is something worth a bit of study.  Yes, learning some PowerShell to create automation tools is a bit of a learning curve, but anything you learn with the intention of telling a computer what to do costs you some amount of learning time, and pays you back in some amount of control over the computer.  Or, in other words:

  • GUIs are not intuitive:  You may not recall it, but GUIs have a learning curve.  No one guesses double-clicking.  Few guess that clicking the little box with the "x" in it up in the upper right-hand corner of a window closes that window, or that the one with the square in it maximizes the window, and so on.  And finding NIC properties in Control Panel... don't get me started.  I'd might say that GUIs are intuitive... once someone explains them to you.  It's a quick study, but a study nonetheless.  And it pays off, as you can get to email, the Web and so on, but it doesn't help you automate most things.  To a small extent, learning a new GUI involves a bit of "watch that first step, it's a lulu." 
  • Command line's harder, but it's the start in automation: Learning a command line tool is usually a bit harder than a GUI tool.  You probably use ping, ipconfig, chkdsk, nslookup (although you'd like DIG better, trust me), xcopy or robocopy... all good tools, and some of them help save you time through automation and/or flexibility.  But they are all admittedly harder than a GUI tool.  What exactly is that option on Robocopy that speeds things up by creating more threads?  (/mt:15, "create 15 threads.")  How do I do just one ping?  (ping -n 1 ipaddress.)  Which command compares two files and delineates their differences?  (FC.)    More stuff to remember, but more payback than from GUI tools.  Again, "watch that first step...," and if the first step in my GUI example was four inches off the ground, the first step for some command-line tools is six inches off the ground... but with the promise of some payback.
  • PowerShell is an investment, but not that big of one:  I'm not going to lie to you -- getting started with PowerShell is even harder than learning just one command line tool, harder than just learning ping, chkdsk, nslookup or the like.  Let's call that first step eight inches off the ground.  But once you learn one or two PowerShell commands, the rest... just flow.  Look:  I'm not a programmer, I don't have a computer science degree.  But after having learned a few dozen PowerShell cmdlets to get some administrative tasks done more quickly and easily, I started gluing two or three of them together into little "one liner" automation tools.  Once I'd done that a few times, I was quickly convinced of their time-saving power, and I've been teaching about them for the past couple of years.  (Join me a week from now in Vegas Friday, 2 November 2012 and you can learn a day's worth.)  Learning to take the next step and start creating more complex scripts seemed like a better and better idea, and so this morning I sat down and bolted together a not-bad first try, something that will be useful (to me, at least) in setting up Server 2012 systems -- and I want you to think about it as well.  We all have to find where we find the best balance in "how much I'm willing to invest up front in learning an admin tool" versus "how much I think it'll pay off," but trust me when I say that I've taken that measure more than a few times in IT, and PowerShell has yielded more productivity payback than any other scripting tool.
  • I'd need pretty good glasses to "C#:"  Continuing along in this vein, I'd call VBScript about a 16-inch first step, and VB.NET about 36 inches... about a meter.  And let's not even talk about tackling C#.  Heck, some variation of C's probably how they built the first ipconfig.  I wonder, though if they got it done in four hours.  (Heh heh heh.)

I hope you find get-ipinfo useful, and I'd love to hear what you think.  As always, I'm at help@minasi.com.

If, however, you already know a bit of PowerShell, you might want to learn a bit about how I built the thing.  If so, read on.  (Warning:  again, it's not a complete explanation of scripting, just some notes that fill in the extensive comments.  So if you've never done any PowerShell, then don't worry about skipping the following section.)

Expert Section -- Building Get-IPInfo:  Some Background

As I said, I wrote get-ipinfo to get a better feel for how far it made sense to go down the PowerShell automation trail, so if you're interested, here are a few notes on what I did and how I did it.  I don't have the space or time to explain everything, but here's basically how I approached it. 

Figure Out What You're Looking For

I knew that my "better IPCONFIG" (or, at least, a better IPCONFIG for me) needed about two dozen pieces of data.  A very shortened version of that might be that I needed my script to extract

  • The computer's hostname, DNS suffix
  • The names of all of its NICs, what would be something like "local area connection," "local area connection 2," and so on in a pre-Windows-8 computer.  The interface numbers on those NICs would be helpful, too, as would link speed.
  • The IP addresses on those NICs, their subnet masks, their MAC addresses, default gateways, DNS servers and the like.

Of the bunch of them, the first was the hardest, believe it or not -- it was the only one that I finally had to surrender and just Google.  Anyway, I just collected the host name by grabbing the value of SET COMPUTERNAME in the environment variables.  Read the script -- it's about 75% comments (they're the lines that start with "#") -- and you'll see how I did it.  (Oh, and speaking of comments ... once you no longer care about how I built the thing, you can you can make the module a whole heck of a lot faster if you go back and delete every line that starts with "#" -- they slow things down.)  The DNS suffix lives in the Registry -- I've automated it before -- and the DNS suffix search order came from a new cmdlet, get-DNSClientGlobalSetting.  The command to gather the hostname looks like this:

$Hostname = (Get-Content ENV:Computername)

The command part on the right uses a cmdlet called get-content to get the contents of an environmental variable named "Computername."  Terse, yes, but readable.  Once we've got that value, we want to keep it handy in something called a "variable," a bit of scratch pad space in memory.  The name is "$Hostname" rather than "Hostname" because variable names in PowerShell must start with a dollar sign.

Getting the DNS domain suffix from the Registry is sort of similar.
 

$PrimaryDNSSuffix = (Get-ItemProperty HKLM:\System\CurrentControlSet\Services\Tcpip\Parameters)."NV Domain"

Wonder how I knew to use get-itemproperty?  I didn't know, so I just typed "help registry" at the PowerShell command line.  Now we've got the suffix in $PrimaryDNSSuffix.

Next I want the whole DNS suffix search list.  I already knew this because I'd quickly played with the DNS-related cmdlets and came across Get-DnsClientGlobalSetting  a run of that looked like this:

PS C:\Windows\system32> get-dnsclientglobalsetting

UseSuffixSearchList : True
SuffixSearchList : {bigfirm.com minasi.com}
UseDevolution : True
DevolutionLevel : 0

So now I knew that get-dnsclientglobalsetting produced four things, of which I wanted just one -- its "SuffixSearchList" value.  To extract that, I just type this:

$DNSSuffixSearchList = (Get-DnsClientGlobalSetting).suffixsearchlist

Putting the Get-DnsClientGlobalSetting cmdlet into parentheses and then adding ".suffixsearchlist" says, "retrieve the value of Get-DnsClientGlobalSetting, but only keep the value of the suffixsearchlist property."  Now that we've got our first three items, let's see how to put them on the screen.  If I'm to mimic IPConfig, I want to produce some output that looks something like

Windows IP Configuration
<blank line>
 Host Name................:  <whatever its host name is goes here>
 Primary DNS Suffix.......:  <whatever its suffix is goes here>
 DNS Suffix Search List...:  <whatever its search list is goes here>

Writing out text like "Windows IP Configuration" or " Host Name . . . . . . . :" is easy in a script -- just type the text with quotes around it.  Here are the first few lines:

""
"Windows IP Configuration"
""
The effect of that is to leave a blank line, then a line with "Windows IP Configuration," and another blank line.  Then I can glue together a literal string of text like "Host Name .......:" to the value of a variable with a "plus" sign, giving me the next few lines:

" Host Name................: " + $Hostname
" Primary DNS Suffix.......: "+ $PrimaryDNSSuffix
" DNS Suffix Search List...: " + $DNSSuffixSearchList
 

From this point on, that's all this script is doing -- gathering some interesting bit of data into a variable, then putting some literal text on the screen, followed by the variable.  But where to get those data?  Where to get NIC names and indexes, IP addresses and subnet masks?  Heck, by comparison, that was easy.  It gave me an excuse to spend a morning playing in my new candy store -- those get-netsomething cmdlets.  Running get-netadapter showed a lot of stuff, but I wanted it laid out a bit better so I piped its output to another PowerShell cmdlet called format-list and abbreviated "fl," so typing

get-netadapter | fl

produced this:

PS C:\> get-netadapter|fl


Name : Ethernet
InterfaceDescription : Intel(R) PRO/1000 MT Network Connection #3
InterfaceIndex : 20
MacAddress : 00-0C-29-FD-28-FF
MediaType : 802.3
PhysicalMediaType : 802.3
InterfaceOperationalStatus : Up
AdminStatus : Up
LinkSpeed(Gbps) : 1
MediaConnectionState : Connected
ConnectorPresent : True
DriverInformation : Driver Date 2010-03-23 Version 8.4.13.0 NDIS 6.0

Name : Internal
InterfaceDescription : Intel(R) PRO/1000 MT Network Connection #2
InterfaceIndex : 17
MacAddress : 00-0C-29-FD-28-F5
MediaType : 802.3
PhysicalMediaType : 802.3
InterfaceOperationalStatus : Up
AdminStatus : Up
LinkSpeed(Gbps) : 1
MediaConnectionState : Connected
ConnectorPresent : True
DriverInformation : Driver Date 2010-03-23 Version 8.4.13.0 NDIS 6.0

Name : External
InterfaceDescription : Intel(R) PRO/1000 MT Network Connection
InterfaceIndex : 12
MacAddress : 00-0C-29-FD-28-EB
MediaType : 802.3
PhysicalMediaType : 802.3
InterfaceOperationalStatus : Up
AdminStatus : Up
LinkSpeed(Gbps) : 1
MediaConnectionState : Connected
ConnectorPresent : True
DriverInformation : Driver Date 2010-03-23 Version 8.4.13.0 NDIS 6.0

And yes, it looks like a mess initially, but give it a second look and you'll notice a few things.

  • The data's grouped by NIC, and there are three NICs on this computer.
  • I was looking for the interface index (which computers like to know) and the name like "Internal" or "External" -- names I gave the NICs -- that people like to know.  Looking at the output, we can see that those two things are called the "InterfaceIndex" and the "Name."  Other cmdlets give them different names -- one I can think of uses "IfIndex" and "IfAlias" -- but this particular one uses InterfaceIndex and Name.  Let's file that information away.
  • Oh, look... there's a LinkSpeed.  Cool, IPCONFIG doesn't have that, and it seems interesting.  Similarly, there's the "what kind of NIC is this" label, the "Intel brand blah blah" label, and IPCONFIG used that, if I recall, so let's also remember LinkSpeed and InterfaceDescription.  And the MAC Address at "MacAddress," and some "is it working?" info are present in InterfaceOperationalStatus, AdminStatus, and MediaConnectionState.  Very nice.

If it sounds at this point like I'm just shopping around, I am -- I know that I've got some information  that I absolutely must acquire, and while I'm at it, I notice some other things that solve my "gee, it'd be nice if we could..." problems (MAC address and NIC description) as well as that new LinkSpeed information.  So I make myself a note that get-netadapter has such-and-such bits of information.

I also said that I wanted IP address and subnet mask information.  Get-NetIPAddress supplied that, as you'll see if you try it out on a 2012 or Win 8 system.

Capture and Control the Information

Again, I don't want all of the info in get-whatever, just parts of it, just as before with get-dnsclientglobalsetting.  Again, this is a big topic and looking at the comments in the script will illuminate things a bit, but instead of just typing "get-netadapter," try adding the parentheses and an interesting-sounding property name, like

(get-netadapter).name

Typing "get-netadapter" tells PowerShell to go grab everything that it knows about these three NICs, and it does that, packaging that data up into something that Windows (well, the part of Windows called ".NET," anyway) calls "objects."  But we're only interested in one part of those three NIC objects, what Windows calls one "property" of those objects -- the name.  In my case, I'd see this output:

PS C:\> (get-netadapter).name
Ethernet
Internal
External
PS C:\>

We can put this into a variable, as before:

PS C:\>
PS C:\> $NICs = get-netadapter
PS C:\> ($NICs).name
Ethernet
Internal
External
PS C:\>

That's useful, let's try something else first.  Type these two lines:

$NICs = get-netadapter
$NICs

When you do that -- just type $NICs on a line by itself -- PowerShell shows you the exact same information that it would have shown you if you'd just typed "get-netadapter."  It's like $NICs froze time and preserves the answer to the question, "what happens when I type get-netadapter" for eternity-- or, rather, until you exit PowerShell.

That dumps out the NIC names, but again it'd be nice to add some extra text.  In this example, $NICs contains three objects because this particular system has three NICs.  We'll need a command that lets us unpack those objects one at a time so we can do something separately to each object.  Try this out:

PS C:\> $NICs = get-netadapter
PS C:\> $NICS | foreach { $_.name + " is a NIC's name."}
Ethernet is a NIC's name.
Internal is a NIC's name.
External is a NIC's name.
PS C:\>

That demonstrated two  things we'll need to understand the entire get-ipinfo script.

First, the "foreach" command takes all of the objects in a variable -- three NICs in $NICs, in this case -- and performs some set of actions on each of those objects, one at a time.  Note the "|" or "pipeline" symbol -- the idea is that PowerShell takes the output of you just typing "$NICs," which you've seen by now just dumps all of the raw NIC data onto the screen, and instead of dumping it on the screen, PowerShell takes the output of $NICs and runs that output down an imaginary pipeline to whatever waits on the other side, which in this case is the command "foreach."

Second, there's some new variable named "$_."  (Recall all variable names must start with "$.") That variable is said aloud "the pipeline" but is spelled "$_" because some nimrod thought that instead of calling it "$pipeline" or the like that "$_" would be shorter to type and because "_" sorta looks like a pipe laying on the ground.  Anyway, "$_" means "what's ever in the pipeline at the moment," and so you can probably see that "$_.name" is just the "name" property associated with whatever's in the pipeline, and what's in the pipeline is a NIC object.  Try typing this:

$NICs | foreach {$_.name}

and all it'll do is just dump NIC names on the screen.  I wanted something prettier and so I wanted to bolt the text " is a NIC's name." on the end, so I used the "+" plus sign, which again in PowerShell lets me glue two strings together.  So Foreach produces a NIC's name and then the string "is a NIC's name.," and so we get our output.

At this point, then, we have cmdlets that produce the data we need, variables that capture their output, a foreach statement that sequentially processes all of the objects produced by the cmdlet, and the ability to add decorative text around it to make it more readable.  Armed with that information, try going back and picking the PowerShell script apart.  If you do, however, I imagine you'll soon want to know...

How To Modify the ifconfig.PSM1 File

I really hope that after you've run get-ipinfo a few times you will of course still love the little guy... but you'll start to want more.  You'll want to try making small tweaks and then big changes to the script.  (It's the best way to get started with a programming language.)   

One reason that you'll probably want to mess with it is because in its current state, the thing's a bit complex, and so at first I hope you'll want to yank some pieces out of it so that you can get it down to an understandable level.  Along those lines, one of the best ways to make the script shorter and more concise is to remove its comments.  You can do that like this:

  • Any line starting with "#" is a comment and doesn't matter.
  • Any information between a "<#" and a "#>" is a big "block comment," and it, like the comment, is only there for us humans to understand.  Flense the file of the comments, and it'll be a much more tractable few dozen lines.

Also, you already know that you can change the file with Notepad, but you might not know that PowerShell's a little weird in the way that it reads the file.  The first time you run get-ipinfo, PowerShell "takes a picture" of the ifconfig.psm1 file and ignores any changes you make to it until you exit PowerShell and return.  That's too much work, so when you do make a change to ifconfig.psm1, get PowerShell to notice it by typing

remove-module ifconfig

The value of making PowerShell unload the module is that the next time you run get-ipinfo, that forces PowerShell to re-read the module... and thus to recognize your changes.

The second reason that I hope you'll want to change the module is that as you come to understand it for the simple thing that it is that you will no longer be much in awe of my PowerShellian skills, and will want to make it different and better.  "Why doesn't this run remotely, so I could type get-ipinfo -computer distantpc.bigfirm.com?"  Or perhaps, "hey, I liked knowing the name of the DHCP server that I got my lease from, why did Mark leave it out?"

And seriously, dear reader, if that happens, then I will be a happy man, as I will have infected you with one of the most profitable addictions of all time -- the programming bug.  It'll burn up your time and it's harder to shake than that "Call Me Maybe" earworm, but once you've got it, you might just find yourself being worth another ten grand or so a year.

As Tony Shalhoub's character Adrian Monk used to say in Monk, "you'll thank me later."  Thanks for reading!

 

 

Upcoming Conferences


  • I will be keynoting the free Tampa IT Pro Camp 2016 on 20 August 2016. Great speakers, sign up now to learn great stuff from some terrific speakers.  https://www.eventbrite.com/e/tampa-it-pro-camp-2016-tickets-24569378673 and tell 'em Mark sent you.
  • I will be presenting at IT/Dev Connections in Vegas the week of 10 October. Http://www.itdevconnections.com/dc16/Public/Enter.aspx for more info.
  • I will also be speaking at the Intersection show also in Vegas the week of 24 October.  Visit https://next.devintersection.com for more info. 
  • December TechMentor is in Orlando this year and I'm keynoting about Server 2016. https://techmentorevents.com/Home.aspx for all the scoop!
I hope to see some of you at one of these shows!

To Subscribe, Read Old Newsletters, Send Me a Comment or Change Your Email Address

To subscribe: (which just means I'll send you about a three tweet-sized message in plain text via email including a link to my latest newsletter), please visit http://www.minasi.com/nwsreg.htm.

To change e-mail or other info, drop me a line (haven't figured out a secure method yet).

To read old newsletters: visit http://www.minasi.com/nwstoc.htm and, if you like 'em, please consider subscribing.

To send me a comment:  I'm at help@minasi.com.

All contents copyright 2012 Mark Minasi.  I encourage you to quote this material, so long as you include this entire document. Thanks very much for reading, and see you next time.