Monthly Archives: June 2011

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!

Get-Member: Powershells most powerfull cmdlet!


Get-Member is by far my favorite and most used cmdlet. It allows you to so what you can do or get from an object.

Before I get in to the meat of the cmdlet, I want to go over some of the terms, since I know there are a lot of admin type people learning powershell and this is more so a developer concept.

Powershell (and .NET) works entirely in objects. Even a simple string is an object, so what’s an object?

An Object is an instance of a class, so then, what’s a class?

The class is what defines the object. It tells you what you can do with your objects and how its done. It’s the Members that let you work on the object.

Members are the Properties, Methods and Events of an object that let you manipulate it. There are other member types, but those are the primary ones.

Lets take a look at a simple String object

$str = “Hello World”

$str | gm

We’ll see it print out a TypeName and a list of members, something like this.

TypeName: System.String

Name             MemberType            Definition
—-             ———-            ———-
Clone            Method                System.Object Clone()

Length           Property              System.Int32 Length {get;}

 

The first thing that should catch your eye is the TypeName, which is the .NET class that the object is, in this case it’s a System.String

If you have Shay’s Get-MSDNInfo function then you can easily get to the MSDN doc’s for an object of this type.

Get-MSDNInfo $str

At any rate, now that we can see the members of this object, we have a pretty good idea of what we can do with it. In the case of a System.String we’ll see that we mostly have methods available to us. You can access any of the members of an object with dot notation.

$object.Member

$str.ToUpper()

Perhaps you can already see why this is my favorite cmdlet. If I run a cmdlet that someone else created or if I am working with some .NET stuff and I get an object back and I don’t know what type it is or what I can do with it, I just toss it to Get-Member and it gives me what I am able to do with that object.

A WORD OF CAUTION!

If you have a collection of something, lets say a collection of strings, you’ll notice that depending on how you call Get-Member (shorthand being gm) you’ll get a different return.

$str = @("Hello","World")
$str | gm
gm –InputObject $str

In this case, powershell assumes you know you have an array, and is showing you what is in that array, not the array object itself. So in the first case, $str | gm you’ll see the TypeName is System.String, which is what is in the array, basically the same as doing $str[0] | gm

On the other hand, if you pass the object Get-Member via the inputobject parameter, you’ll get the TypeName of the collection, in this case it’s a generic System.Object[]. One important thing to note on that type name is the [] at the end, which is what indicates this is a collection.

In the case of a collection of strings, its not so important, but lets say you are using a  DirectorySearcher and use the FindAll() method, what you actually get back is a System.DirectoryServices.SearchResultCollection so depending on how you use Get-Member it will either tell you it’s a SearchResultCollection or a SearchResult, with each having different methods and properties to work with.

 

When in doubt, do it both ways.

 

There is one other thing to note here. When you do $object | gm, Get-member will show you each UNIQUE datatype in a collection, so for example, if you do the follow.

$arr = 1,"hello"
$arr | gm

You’ll get two TypeNames back, System.Int32 and System.String.

You’ll see this more so if you do a Get-Member on a Get-Eventlog. With Event Logs and WMI you get the namespace with it, I havent been able to learn why that is yet.

 

I hope this helps you spend more time in powershell and less time googling object different objects!

File to function / String to ScriptBlock


Someone asked a question in forum that got me thinking about PS1 files and functions. The problem was they couldn’t run PS1 files due to the security on the machine. Mostly they wanted to do this to learn, and I suspect it was just from running files they’ve download.

At any rate, this got me thinking, how could I import a PS1 in to my session as a function? Well after a little tinkering, I found a way.

###create ps1 file for test

Set-Content -path testadd.ps1 -value ‘
    param (
    [int] $variable1,
    [int] $variable2
    )
    $variable3=$variable1+$variable2;
    $variable3
    ‘

##create a function from our testadd.ps1 script

New-Item -Path function: -Name SimpleAdd -ItemType function -Value ([scriptblock]::create((gc .\testadd.ps1) -join [environment]::newline))

SimpleAdd 1 2

That’s all there is to it! Not really sure how useful this is, but was a neat little experiment.

Enjoy!

Creating a timer event in Powershell


Recently I needed a timer to monitor something so I did a quick google search which to my surprise didn’t come up with much. Perhaps because this isn’t too hard, but still, I thought I would post a little something on how to do this.

If you are the developer type person then you might want to take a look at this article on the different .NET timer classes. A good read and good to know but not really needed for this post.

The timer class I’ll be using is the System.Timers.Timer  (Which can be shortened to Timers.Timer because powershell assumes the system. namespace )

$timer = new-object timers.timer

$action = {write-host "Timer Elapse Event: $(get-date -Format ‘HH:mm:ss’)"}
 

$timer.Interval = 3000 #3 seconds 

Register-ObjectEvent -InputObject $timer -EventName elapsed `
–SourceIdentifier  thetimer -Action $action


$timer.start()

#to stop run
$timer.stop()
#cleanup
Unregister-Event thetimer

You’ll notice it will start to spit out the Timer Elapsed Event notices, which is all well and good, but doesn’t do much for us.

 

In my case I have a background process going that has an event that I’ve registered for, but, I’ve found a problem with it (a post to come on that) so I need a timer to monitor this object. Lets say my background job sets a variable, $complete, to 1 when its done. We can monitor that variable building off of the pervious code.

$complete = 0
$action = {
write-host "complete: $complete"
if($complete -eq 1)
   {
     write-host "completed"
     $timer.stop()
     Unregister-Event thetimer
   }
}

Register-ObjectEvent -InputObject $timer -EventName elapsed `
–SourceIdentifier  thetimer -Action $action


$timer.start()

#to stop
$complete = 1

Once we change the $complete variable to 1 and the timer goes off it checks that, finds that it should stop and cleans itself up.

 

Enjoy!

Methods for working with Active Directory in Powershell


— If you were directed here from the forums, pay special attention to the notes. I am doing this because so often people post code without telling you what tools you need to run it! —

I often times see people heading over to the forums to get some help with working with AD type stuff and don’t really know where to start or what the options are.

The biggest part over looked (and what I’m covering here) is the methods available for working with the AD from Powershell.

You’ve got three options outlined below with pro’s and con’s

  • Active Directory modulefrom Microsoft (RSAT)
    • Pros
      • Easy to use
      • Available on Windows 7 and 2008 (RSAT feature)
      • Built in/Native
    • Cons
    • Notes:
      • cmdlets are in the standard verb-noun format and are documented on Technet pretty well
  • Quest ActiveRoles Management
    • Pros
      • Easy to use
      • Works on just about anything
    • Cons
      • Requires the module to be installed to use it (bad for scripting)
    • Notes
      • all cmdlets are in the format verb-QAnoun so, if you see a cmdlet with QA you need the quest tools
  • .NET Directory Services
    • Pros
      • Works anywhere
      • No requirements
      • Great for scripts to assure they always work
    • Cons
      • Requires more code
      • Deeper understanding of AD to utilize
    • Notes
      • nice shortcut to DirectoryEntry by casting: $domain = [ADSI] “LDAP://path”
      • $searcher = [ADSISearcher] “LDAP filter query

My personal choice is the .NET method, since I can use it in a script and know for sure it will work, but, it’s a LOT more coding. If you are doing admin type work, you might want to look at either the Quest tools or using the Active Directory module. If you want to know if the AD module is installed and available you can run the following command

    Get-Module –list

You should see the ActiveDirectory module in the list. You can then import it if you’d like to use it

Import-Module ActiveDirectory

If you are unsure if you have ADWS running on your domain attempting to import the module will tell you if it cant find one.

and you can use the link above to get started or simply list out the commands in that module.

Get-Command –Module ActiveDirectory

I’m sure you’ve noticed I haven’t gone in to great detail on how to use these, install or verify requirements. There is a ton of info out there on that, this is mostly to help you figure out which methods are out there, and if someone pasted code, to help you figure out which one the code requires.

Hope this helps, if you’d like to see more details on any of this let me know!