Creating a module for powershell with a format file


So a little while ago I created a netstat function for powershell that doesn’t use the netstat.exe from windows but rather uses pinvoke to call some API’s. Perhaps a bit over kill, but was a fun little project. The problem I ran in to was the display of that info. So, I took what was there and turned it in to a module, and here is how its done.

So, for a module to be easily accessible it needs to be in one of two locations depending if you want it user or system level.

 

Step 1 – Create the modules folder!

User Level Module Location: $home\Documents\WindowsPowershell\Modules

Machine Level Module Location: $HOME\Modules

Where you store it is up to you. Each module must have a folder, in this case, I called it NetworkUtil and the way modules work is it loads the PSM1 file with the same name as the folder (which is module name).

Step 2 – The files

you could have a very simple module that is one ps1 file, and just name it the same as the folder and you’re good, but because our script may down the road involve a few more functions (in the form of PS1 files) as well as special formatting, we’re going to create a few files.

NetworkUtil.psm1 – The module file that tells it what files are involved in this module.

Network.Format.ps1xml – The file that contains info on how we want our function displayed.

NetworkUtil.psd1 – a manifest module, basically it gives some info about it and is of a standard format. This can be copied from http://msdn.microsoft.com/en-us/library/dd878337(VS.85).aspx and modified to suit your modules needs. There is ONE important modification here, and that’s for our format file. in the FormatsToProcess assign ‘NetworkUtil.Format.ps1xml’.

Get-Netstat.ps1 – And of course, our script file

Step 3 Give those files some content!

Easy ones first.

The Get-Netstat.ps1 should contain the netstat function we created before

Next, the NetworkUtil.psm1 needs to contain one lonely line for now.

. $psScriptRoot\Get-Netstat.ps1

the NetworkUtil.psd1 which as indicated above can be copied from http://msdn.microsoft.com/en-us/library/dd878337(VS.85).aspx with that one minor modification;

FormatsToProcess = ‘NetworkUtil.Format.ps1xml’

 

Now for the fun part, the format file. More info can be found here, but basically its just an XML doc with some pretty basic info. We define the header names and size and then defile the properties that it should display under those headers. This is a real basic format file, but it does the trick

<?xml version="1.0" encoding="utf-8"?>
<Configuration>
  <ViewDefinitions>
    <View>
      <Name>DefaultView</Name>
      <ViewSelectedBy>
        <TypeName>Connection</TypeName>
      </ViewSelectedBy>
      <TableControl>
        <TableHeaders>
          <TableColumnHeader>
            <Width>4</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Width>6</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Width>15</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Width>6</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Width>15</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Width>6</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Width>15</Width>
          </TableColumnHeader>
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <TableColumnItems>
              <TableColumnItem>
                <PropertyName>protocol</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>PID</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>LocalIP</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>localport</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>remoteip</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>remoteport</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>state</PropertyName>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
      </TableControl>
    </View>
  </ViewDefinitions>
</Configuration>

 

Nothing to special going on here, but it surely makes it a lot easier to read!

 

Now we just need to import our module

Import-Module NetworkUtil

And we’re ready to go!

 

Get-Netstat

Because our netstat is now so cool we can take a look at all TCP connections that are not on the loop back connection.

Get-Netstat –TCPonly | where {$_.localip –ne “172.0.0.1”}

or perhaps only established connections and in order of local port.

Get-Netstat | where {$_.state –eq “established”} | sort localport

Maybe we want to see all web sessions we are connected to.

Get-Netstat | where {$_.remoteport –eq 80}

Now we want to see the names (name resolution is done on request so this might slow down to regular netstat speed)

Get-Netstat | where {$_.remoteport –eq 80} | select RemoteHostName,State

 

Once I found a good place to upload this I’ll make this module downloadable.

Enjoy!

Advertisements

About jrich

I am the Solutions Architect for Apex Learning in Seattle WA. I've been working with computers since I was 13. Started programming when I was 14. Had my first IT job as tech support at an ISP at the age of 15 and became a network admin at the age of 17. Since then I've worked at a variety of small to mid size companies supporting, maintaining and developing all aspects of IT. Mostly working with Windows based networks but have recently been working with Solaris system as well. I created this blog mostly as a place for me to take my own notes, but also share things that I had a hard time finding the info for.

Posted on June 23, 2011, in WMF (Powershell/WinRM) and tagged , , . Bookmark the permalink. 8 Comments.

  1. I like the idea and while I don’t completly understand the code, I would like to use this module. However, I must have done something wrong. When I try to run it, I get nothing. :

    PS Scripts:\> import-module networkUtil
    PS Scripts:\> get-command -module NetworkUtil
    PS Scripts:\>
    PS Scripts:\> Get-NetStat
    The term ‘Get-NetStat’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:12

    I put all four files in:
    C:\Documents and Settings\mfelkin\My Documents\WindowsPowerShell\Modules\NetworkUtil

  2. Sounds more like a problem with the netstat, not so much the format file.
    Im guessing you are missing the Export command at the end of the file like so

    Export-ModuleMember get-netstat

  3. At the end of which file? I am confused, can you tell?

    • this is in addition to the get-netstat.ps1 file mentioned in this post. there is a link to it. that is the get-netstat function, this post is on creating a format file for that function and wrapping it in a module. so if you are just interested in the get-netstat functionality, and not so much the ways to change the look of the output, then i’d just grab the script from that one post.

  4. Good piece of code and a good excercize.

    I reformatted the C# code so that it is readable. It is worth looking at and I wanted to be sure I knew what was happenning.

    For anyone else that is interested here is the C# bit reformatted for readbility and colorized. It is a nice piece of code. I prefer the code formmater to teh WordPress line numbered version as it is harder to read. Couple that with the loss of all indents it becomes imposible to read on the web and in a text file.

    http://www.designedsystemsonline.com/upload/netstatcs.htm

    It would be helpful if you posted a link to your module. Consider using Skydrive. It is free and easy to use.

    My main purpose here was to try and discover a way to easily marshall an array of structs. Your code does it by returning an array. Marshalling an array as an out argument is a bit more complicated with PowerShell since PowerShell really knows nothing about pointers.

    Good blog and good post. Keep up the good bloggin.

  5. Step 1 lists an incorrect module location for System (or Machine Level Module Location).
    System: $pshome\Modules
    Current user: $home\Documents\WindowsPowerShell\Modules

    File name “Network.Format.ps1xml” listed in Step 2 does not match the manifest entry “FormatsToProcess = ‘NetworkUtil.Format.ps1xml’” in Step 3.Also change open/close quotes to single quotes.

    localhost = 127.0.0.1, not 172.0.0.1 in the examples

    Using Import-Module NetworkUtil -Verbose shows that NetworkUtil.psd1 and NetworkUtil.Format.ps1xml load, and don’t attempt to load NetworkUtil.psm1 and subsequently Get-NetStat.ps1, so the Export-ModuleMember Get-NetStat does not work and the function is not available.

    • This was mostly about the format file and didnt detail the module part well. you need to tell it to load the PSM1 file, with PS v2 there is an entry in the PSD1 called “ModuleToProcess” which is at the top of the file. in V3 its RootModule or something like that. I usually change it to the V2 name since that works fine in V3/4, why they changed it blows my mind.

      • The link to .psd1 standard template appears to be in PS v3 format (containing RootModule). I had to replace RootModule with ModuleToProcess = ‘NetworkUtil’ which didn’t exist.

        So, step 3 includes two modifications to make this work as a module…
        FormatsToProcess = ‘NetworkUtil.Format.ps1xml’
        ModuleToProcess = ‘NetworkUtil’ or RootModule = ‘NetworkUtil’

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: