Manage WSUS with Powershell

Many of you probably use WSUS as your enterprise patching solution.  For those of you who are unfamiliar with WSUS, please check out this link for more information. With WSUS 3.0, you are now able to download and install the WSUS Console to your client machine and with this, you can now make use of the API’s on your own machine instead of working on the server to perform WSUS related tasks via PowerShell. I am currently working on a WSUS module and will post it once completed. Right now I mostly have reporting functions with a couple functions that allow for setting email notifications, starting a sync and configuring the update scope.  I still have a little ways to go in building functions that will allow you to approve updates and some other things.

Once you have installed the console, you can then take advantage of the assemblies. For this posting, I will show you how to connect to the WSUS server and perform a couple simple queries for a list of all computers reporting to WSUS and also how to perform a sync and view the progress of a sync via PowerShell.

First off, you will need to add the assemblies that so you can make the connection to WSUS. Once you have done that, you can access the .NET namespaces, listed here. Then you can connect to the WSUS server using the code snippet below.  Since I am not making a secure connection (443), I set the second value to $False.

$wsusserver = "dc1"
#Load required assemblies
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False)

Looking at the $wsus variable, you can see some information regarding the server such as the version and port number.

Untitled

You can also use the Get-Member cmdlet to list all of the available methods you can use for various actions against the WSUS server.

$wsus | gm

Untitled

There are too many of these to go into here, but the first one I am going to show is the GetComputerTargets() method. This method will allow you to query the WSUS server for all clients that are reporting to the server. You can use this to find out when the last check-in time was for each client, the last sync time and if the sync was successful.

For instance, if you want to find out just the last time each client has reported status, you could use something like this:

$wsus.GetComputerTargets() | Select FullDomainName, LastReportedStatusTime

Untitled

Here is a script that will perform the task for you:

function Get-WSUSClientCheckIn {
<#
.SYNOPSIS
    Retrieves the last check-in times of clients on WSUS.
.DESCRIPTION
    Retrieves the last check-in times of clients on WSUS. You will need to run this on a machine that
    has the WSUS Administrator console installed.
.PARAMETER wsusserver
    Name of WSUS server to query against.
.PARAMETER secure
    Determines if a secure connection will be used to connect to the WSUS server. If not used, then a non-secure
    connection will be used.
.NOTES
    Name: Get-LastCheckIn
    Author: Boe Prox
    DateCreated: 24SEPT2010

.LINK
    https://boeprox.wordpress.org
.EXAMPLE

#>
[cmdletbinding(
	DefaultParameterSetName = 'wsus',
	ConfirmImpact = 'low'
)]
    Param(
        [Parameter(
            Mandatory = $True,
            Position = 0,
            ParameterSetName = 'wsus',
            ValueFromPipeline = $True)]
            [string]$wsusserver,
        [Parameter(
            Mandatory = $False,
            Position = 1,
            ParameterSetName = 'wsus',
            ValueFromPipeline = $False)]
            [switch]$secure
            )
#Load required assemblies
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
#Connect to WSUS server
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False)
#Gather all computers in WSUS
$computers = $wsus.GetComputerTargets()
#Iterate through computers to gather last check-in time
ForEach ($computer in $computers) {
   New-Object PSObject -Property @{
   Computer = $computer.FullDomainName
   LastCheckin = $computer.LastReportedStatusTime
        }
    }
}

Starting a WSUS synchronization is a little more hidden.  You have to first use the GetSubscription() method and then call the StartSynchronization() method.

$sub = $wsus.GetSubscription()
$sub.StartSynchronization()

This will kick off the sync process on the remote WSUS server. You can also monitor the sync status either from the console or even through PowerShell using the GetSynchronizationProgress() method.

Untitled

You could setup a background job to monitor the progress and then send a pop-up alert when the sync has been completed.

That is all for now, next time I will take a look at viewing the updates and target groups on the WSUS server and hopefully will have my module at least in a Beta stage to show and make available for a download to gather feedback on it.

Posted in powershell, WSUS | Tagged , , , | 9 Comments

Retrieving Windows Experience Index via WMI

You may have seen this on your Vista or Windows 7 machine. As you can tell, mine is probably average, but did you know that you can retrieve this locally or remotely via WMI using the Win32_WinSat class?

You can not only retrieve that number but all of the scores that you would normally see via the GUI (see below).

This little function will allow you to view not only your local Windows Experience Index, but also any remote machine’s index as well! The big thing that I changed was translating the value that you would normally get with the AssessmentState property.

PS C:\Users\boe\Downloads> get-winsat -computer “boe-laptop”,”dc1″ | FT -autoComputer   CPU VideoCard PhysicalDisk Graphics Memory WinSPRLevel AssessmentState
——–   — ——— ———— ——– —— ———– —————
boe-laptop 5.1       6.1          5.5      5.3    5.1         5.1 Valid
dc1        N/A       N/A          N/A      N/A    N/A         N/A OS Not Supported

Script posted on the Technet Script Repository

function Get-WinSat{
<#
.SYNOPSIS
Retrieves Windows Experience Index information.
.DESCRIPTION
Retrieves Windows Experience Index information.
.PARAMETER computer
Name of server to retrieve Windows Experience Information.
.NOTES
Name: Get-WinSat
Author: Boe Prox
DateCreated: 20SEPT2010.LINK


https://boeprox.wordpress.org
.EXAMPLE
Get-WinSat -computer “test”
#>
[cmdletbinding(
DefaultParameterSetName = ‘computer’,
ConfirmImpact = ‘low’
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = ‘computer’,
ValueFromPipeline = $True)]
[array]$computer
)
Begin {
#Create empty array
[array]$report = @()
}
Process {
#Iterate through computers
ForEach ($c in $computer) {
#Create temp object
$temp = New-Object PSObject
#Continue if OS is Vista or above
If ((Get-WmiObject -ComputerName $c Win32_OperatingSystem).version -gt 5.3) {
Try {
#Retrieve Windows Experience Index information
$winsat = gwmi win32_winsat -comp $c -ea stop
$temp | Add-Member NoteProperty Computer  $c
$temp | Add-Member NoteProperty CPU  $winsat.CPUScore
$temp | Add-Member NoteProperty VideoCard  $winsat.D3DScore
$temp | Add-Member NoteProperty PhysicalDisk  $winsat.Diskscore
$temp | Add-Member NoteProperty Graphics  $winsat.GraphicsScore
$temp | Add-Member NoteProperty Memory  $winsat.MemoryScore
$temp | Add-Member NoteProperty WinSPRLevel  $winsat.WinSPRLevel
Switch ($winsat.WinSATAssessmentState) {
0 {$assessment = “StateUnknown”}
1 {$assessment = “Valid”}
2 {$assessment = “IncoherentWithHardware”}
3 {$assessment = “NoAssessmentAvailable”}
4 {$assessment = “Invalid”}
}
$temp | Add-Member NoteProperty AssessmentState $assessment
}
Catch {
$temp | Add-Member NoteProperty Computer  $c
$temp | Add-Member NoteProperty CPU  “N/A”
$temp | Add-Member NoteProperty VideoCard  “N/A”
$temp | Add-Member NoteProperty PhysicalDisk “N/A”
$temp | Add-Member NoteProperty Graphics  “N/A”
$temp | Add-Member NoteProperty Memory “N/A”
$temp | Add-Member NoteProperty WinSPRLevel  “N/A”
$temp | Add-Member NoteProperty AssessmentState “Unable to query value”
}
}
Else {
$temp | Add-Member NoteProperty Computer  $c
$temp | Add-Member NoteProperty CPU  “N/A”
$temp | Add-Member NoteProperty VideoCard  “N/A”
$temp | Add-Member NoteProperty PhysicalDisk “N/A”
$temp | Add-Member NoteProperty Graphics  “N/A”
$temp | Add-Member NoteProperty Memory “N/A”
$temp | Add-Member NoteProperty WinSPRLevel  “N/A”
$temp | Add-Member NoteProperty AssessmentState “OS Not Supported”
}
#Add temp object to report array
$report += $temp
}
}
End {
#Display report
$report
}
}

Posted in powershell, scripts | Tagged , , , | Leave a comment

Custom Powershell Objects and Performance

One of the things that I have been seeing are the different ways to compile a report or to create a collection of custom objects in Powershell.  In fact, there was a comment on a previous post saying that I should use the V2 style of custom objects instead of what I was using already. Whether it is creating a custom object using New-Object PSObject and then using the Add-Member cmdlet to add more information to the object, or using a hash table to display the data or some other method to accomplish this task such as Select-Object.

This made me think of not only which one provided the fastest results, but which one would give me the type of output that I desired?

James Brundage’s blog does a very nice jobs discussing the Pros and Cons of using Add-Member vs Select-Object.

MOW, Brandon Shell and Karl Prosser tested this before with some interesting results.  These guys are a lot smarter than me and showed some nice things including using C# code to create a custom object, which turned out to be crazy fast.  I wanted to expand on the testing a little more by adding more objects that were being collected to really see the differences in the time it takes to complete. Now I am still learning C# so I will not be using the C# code that they used in their test.

I am going to be looking at Add-Member, Select-Object and creating a Hash Table to see which one has the best performance and which one gives me the type of output that I am usually looking for, keeping the order of the properties as I have defined at the beginning.

Basically I wrote a script and hard-coded the number of objects and the amount of cycles that each method would be using and then finding out the number of seconds it takes for each method to run. The script I am using will be at the bottom of the post, so feel free to take it and run it on your own machine.  Keep in mind that my results will not match what you may get just because of what each machine might have for hardware and the current processes running on your machine vs. mine.

Here are the sample codes for each method:

Add-Member

for($i = 0;$i -lt 50000;$i++)  {
$a = new-Object psobject
$a | add-member -membertype noteproperty -name test1 -value “test1”
}
 

Select-Object

{for($i = 0;$i -lt 50000;$i++) {
$a = 1 |Select-Object test1,test2,test3,test4,test5,test6,test7,test8,test9,test10
$a.test1 = “test1”
}
 

Hash Table

for($i = 0;$i -lt 50000;$i++)  {
New-Object PSObject -Property @{
test1 = “test1”
}
}

It took a few minutes to run the script and give me the information I needed.

At first I had it writing verbose so I could see how long it was taking. Then I had the bright idea of creating a collection so it would be easier to see and compare each method based on the number of objects and the amount of cycles.

Results from script:

Name                             Objects                        Cycles                       Seconds
—-                                    ——-                        ——                       ——-
Add-Member                     1                         50000                    27.9131198
Select-Object                    1                         50000                    19.3800657
HashTable                        1                         50000                    11.0661309
Add-Member                     2                         50000                    45.7721692
Select-Object                    2                         50000                    18.9221812
HashTable                        2                         50000                    11.8333989
Add-Member                    5                         50000                   100.5090867
Select-Object                   5                         50000                    19.3345412
HashTable                       5                         50000                    14.1277553
Add-Member                  10                         50000                   191.9198304
Select-Object                  10                         50000                    20.0706683
HashTable                      10                         50000                    18.2829811
 

1st run:

Add-Member                   1                         50000                    27.9131198
Select-Object                  1                         50000                    19.3800657
HashTable                      1                         50000                    11.0661309

Breaking this down by number of objects, the first run with only 1 object shows that the Add-Member method was the slowest of the bunch followed by Select-Object and finishing with the Hash Table. Everything is within a decent time of each other, so you might think that any of these would be fine to use.

2nd run:

Add-Member                  2                         50000                    45.7721692
Select-Object                  2                         50000                    18.9221812
HashTable                      2                         50000                    11.8333989

Using 2 objects begin to show the speed difference between Add-Member and the rest of the methods. Where the Add-Member method was only 8 seconds slow before has now jumped up to being 27 seconds slower just by adding an extra object. Select-Object actually was a little faster than before and the Hash Table was slower by milliseconds.

3rd run:

Add-Member                  5                         50000                   100.5090867
Select-Object                  5                         50000                    19.3345412
HashTable                      5                         50000                    14.1277553
 

Using 5 objects really shows the performance hit that using Add-Member creates. It takes 100 seconds to complete this action whereas the Select-Object is 81 seconds faster and the Hash Table is 86 seconds faster. We are talking almost 5 times faster to complete this.

4th run:

Add-Member                 10                         50000                   191.9198304
Select-Object                10                         50000                    20.0706683
HashTable                    10                         50000                    18.2829811
 

Using 10 objects in the last run pretty much sums up what has already been shown, that Add-Member is not the way to go if you are looking for performance when creating a custom object.  Nearly 200 seconds to work with 10 objects across 50000 cycles. Select-Object comes in seconds on this with a run of 20 seconds and the Hash Table custom object was the quickest at 18.2 seconds.

The winner by a nose in this test was using the Hash Table method to create a custom object. The caveat to this is that using a Hash Table means that you will not always get the property order that you put in. See picture below.

To sum it up, if your looking for speed, use Hash Tables, if your looking for a specific order or reporting with custom objects, use the Select-Object or Add-Member methods. To learn more about the differences and when to use each of these, check out this blog.

I know that there are other ways to accomplish this such as using system.collections.generic.dictionary or System.Collections.ArrayList. But my main focus did not concern these this time.

I wanted to do more with the code and remove the hard-coding of the objects with the switch statement, but I simply ran out of time.

CustomObjectPerformance.ps1

[int[]]$objects = 1,2,5,10
[int]$cycles = 50000
$report = @()
ForEach ($obj in $objects) {
Switch ($obj) {
1 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Add-Member custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++)  {
$a = new-Object psobject
$a | add-member -membertype noteproperty -name test1 -value “test1”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Add-Member”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
2 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Add-Member custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++)  {
$a = new-Object psobject
$a | add-member -membertype noteproperty -name test1 -value “test1”
$a | add-member -membertype noteproperty -name test2 -value “test2”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Add-Member”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
5 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Add-Member custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++)  {
$a = new-Object psobject
$a | add-member -membertype noteproperty -name test1 -value “test1”
$a | add-member -membertype noteproperty -name test2 -value “test2”
$a | add-member -membertype noteproperty -name test3 -value “test3”
$a | add-member -membertype noteproperty -name test4 -value “test4”
$a | add-member -membertype noteproperty -name test5 -value “test5”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Add-Member”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
10 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Add-Member custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++)  {
$a = new-Object psobject
$a | add-member -membertype noteproperty -name test1 -value “test1”
$a | add-member -membertype noteproperty -name test2 -value “test2”
$a | add-member -membertype noteproperty -name test3 -value “test3”
$a | add-member -membertype noteproperty -name test4 -value “test4”
$a | add-member -membertype noteproperty -name test5 -value “test5”
$a | add-member -membertype noteproperty -name test6 -value “test6”
$a | add-member -membertype noteproperty -name test7 -value “test7”
$a | add-member -membertype noteproperty -name test8 -value “test8”
$a | add-member -membertype noteproperty -name test9 -value “test9”
$a | add-member -membertype noteproperty -name test10 -value “test10”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Add-Member”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
}Switch ($obj) {

1 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Select-Object custom objects using 50000 iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt 50000;$i++) {
$a = 1 |Select-Object test1,test2,test3,test4,test5,test6,test7,test8,test9,test10
$a.test1 = “test1”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Select-Object”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
2 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Select-Object custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
$a = 1 |Select-Object test1,test2,test3,test4,test5,test6,test7,test8,test9,test10
$a.test1 = “test1”; $a.test2 = “test2”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Select-Object”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
5 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Select-Object custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
$a = 1 |Select-Object test1,test2,test3,test4,test5,test6,test7,test8,test9,test10
$a.test1 = “test1”; $a.test2 = “test2”; $a.test3 = “test3”; $a.test4 = “test4”; $a.test5 = “test5”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Select-Object”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
10 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Select-Object custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
$a = 1 |Select-Object test1,test2,test3,test4,test5,test6,test7,test8,test9,test10
$a.test1 = “test1”; $a.test2 = “test2”; $a.test3 = “test3”; $a.test4 = “test4”; $a.test5 = “test5”
$a.test6 = “test6”; $a.test7 = “test7”; $a.test8 = “test8”; $a.test9 = “test9”; $a.test10 = “test10”
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “Select-Object”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
}Switch ($obj) {

1 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Hash Table custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
New-Object PSObject -Property @{
test1 = “test1”
}
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “HashTable”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
2 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Hash Table custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
New-Object PSObject -Property @{
test1 = “test1”; test2 = “test2”
}
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “HashTable”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
5 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Hash Table custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
New-Object PSObject -Property @{
test1 = “test1”; test2 = “test2”; test3 = “test3”; test4 = “test4”; test5 = “test5”
}
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “HashTable”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
10 {
$temp = “” | Select Name, Objects,Cycles, Seconds
Write-Host -fore Green “Beginning performance test for Hash Table custom objects using $cycles iterations and $($obj) objects”
$run = $(Measure-Command {for($i = 0;$i -lt $cycles;$i++) {
New-Object PSObject -Property @{
test1 = “test1”; test2 = “test2”; test3 = “test3”; test4 = “test4”; test5 = “test5”
test6 = “test6”; test7 = “test7”; test8 = “test8”; test9 = “test9”; test10 = “test10”
}
}}).TotalSeconds
Write-Host -ForegroundColor Cyan “$($run) seconds”
$temp.Name = “HashTable”
$temp.Objects = $obj
$temp.Cycles = $cycles
$temp.seconds = $run
$report += $temp
}
}
}
$report
Posted in powershell | Tagged , , , , | 5 Comments

Scanning ports on multiple hosts

Recently we had an issue that called into the use of checking to see if some ports were open and listening on our servers.  Naturally, we could have used a tool such as portqry.exe to gather this information. However, you can only use it on one system at a time which meant either incorporating it with Powershell and call the .exe when needed.  While a good idea, I wanted to build something that was free of any extra tools and just rely on Powershell itself to complete this task.

After doing some research and looking some examples online, I found that this could in fact be easily done.  Initially I was going to have it scan for TCP ports, but decided that checking UDP ports would be a good idea as well. My goal was to not only be able to scan multiple hosts, but to also scan multiple ports and report back which ones were open and which were closed.

Using the System.Net.Sockets namespace, I was able to create an object that I could then use to test both TCP and UDP ports.

$tcpobject = new-Object system.Net.Sockets.TcpClient
$udpobject = new-Object system.Net.Sockets.Udplient

I can then use the .BeginConnect() method and plug in the hostname and the port that will be tested.

$connect = $tcpobject.BeginConnect($c,$p,$null,$null)
$connect = $udpobject.BeginConnect($c,$p,$null,$null)

I then configure a timeout using the following:

$wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false)

If you expand out what is in the $connect variable, you see this:

AsyncState             :
AsyncWaitHandle        : System.Threading.ManualResetEvent
CompletedSynchronously : False
IsCompleted            : True

This link explains the System.Threading.ManalResetEvent that I am using for the timeout.

The rest of the script uses the Add-Member cmdlet to add items to the created PSObject that holds all of the information for the report. I also make use of string manipulation such as Split(), Replace() and TrimStart() to make the error messages more readable in the report.

I decided to run the port scan against my local domain controller and google.com to show that some ports are open and others are not.  In the case of DC1, only TCP port 53 (DNS) was open and at google.com, TCP ports 80 (HTTP) and 443 (HTTPS) were open.


List of ports:

http://www.iana.org/assignments/port-numbers

My script is also available at the Script Repository.

Code Update 20Feb2011

Script:

function Test-Port{
<#
.SYNOPSIS
Tests port on computer.
.DESCRIPTION
Tests port on computer.
.PARAMETER computer
Name of server to test the port connection on.
.PARAMETER port
Port to test
.PARAMETER tcp
Use tcp port
.PARAMETER udp
Use udp port
.PARAMETER UDPTimeOut
Sets a timeout for UDP port query. (In milliseconds, Default is 1000)
.PARAMETER TCPTimeOut
Sets a timeout for TCP port query. (In milliseconds, Default is 1000)
.NOTES
Name: Test-Port.ps1
Author: Boe Prox
DateCreated: 18Aug2010
List of Ports: http://www.iana.org/assignments/port-numbers To Do:
Add capability to run background jobs for each host to shorten the time to scan.
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Test-Port -computer ‘server’ -port 80
Checks port 80 on server ‘server’ to see if it is listening
.EXAMPLE
‘server’ | Test-Port -port 80
Checks port 80 on server ‘server’ to see if it is listening
.EXAMPLE
Test-Port -computer @(“server1″,”server2”) -port 80
Checks port 80 on server1 and server2 to see if it is listening
.EXAMPLE
@(“server1″,”server2”) | Test-Port -port 80
Checks port 80 on server1 and server2 to see if it is listening
.EXAMPLE
(Get-Content hosts.txt) | Test-Port -port 80
Checks port 80 on servers in host file to see if it is listening
.EXAMPLE
Test-Port -computer (Get-Content hosts.txt) -port 80
Checks port 80 on servers in host file to see if it is listening
.EXAMPLE
Test-Port -computer (Get-Content hosts.txt) -port @(1..59)
Checks a range of ports from 1-59 on all servers in the hosts.txt file

#>
[cmdletbinding(
DefaultParameterSetName = ”,
ConfirmImpact = ‘low’
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = ”,
ValueFromPipeline = $True)]
[array]$computer,
[Parameter(
Position = 1,
Mandatory = $True,
ParameterSetName = ”)]
[array]$port,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[int]$TCPtimeout=1000,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[int]$UDPtimeout=1000,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[switch]$TCP,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[switch]$UDP

)
Begin {
If (!$tcp -AND !$udp) {$tcp = $True}
#Typically you never do this, but in this case I felt it was for the benefit of the function
#as any errors will be noted in the output of the report
$ErrorActionPreference = “SilentlyContinue”
$report = @()
}
Process {
ForEach ($c in $computer) {
ForEach ($p in $port) {
If ($tcp) {
#Create temporary holder
$temp = “” | Select Server, Port, TypePort, Open, Notes
#Create object for connecting to port on computer
$tcpobject = new-Object system.Net.Sockets.TcpClient
#Connect to remote machine’s port
$connect = $tcpobject.BeginConnect($c,$p,$null,$null)
#Configure a timeout before quitting
$wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout,$false)
#If timeout
If(!$wait) {
#Close connection
$tcpobject.Close()
Write-Verbose “Connection Timeout”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “TCP”
$temp.Open = “False”
$temp.Notes = “Connection to Port Timed Out”
}
Else {
$error.Clear()
$tcpobject.EndConnect($connect) | out-Null
#If error
If($error[0]){
#Begin making error more readable in report
[string]$string = ($error[0].exception).message
$message = (($string.split(“:”)[1]).replace(‘”‘,””)).TrimStart()
$failed = $true
}
#Close connection
$tcpobject.Close()
#If unable to query port to due failure
If($failed){
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “TCP”
$temp.Open = “False”
$temp.Notes = “$message”
}
#Successfully queried port
Else{
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “TCP”
$temp.Open = “True”
$temp.Notes = “”
}
}
#Reset failed value
$failed = $Null
#Merge temp array with report
$report += $temp
}
If ($udp) {
#Create temporary holder
$temp = “” | Select Server, Port, TypePort, Open, Notes
#Create object for connecting to port on computer
$udpobject = new-Object system.Net.Sockets.Udpclient($p)
#Set a timeout on receiving message
$udpobject.client.ReceiveTimeout = $UDPTimeout
#Connect to remote machine’s port
Write-Verbose “Making UDP connection to remote server”
$udpobject.Connect(“$c”,$p)
#Sends a message to the host to which you have connected.
Write-Verbose “Sending message to remote host”
$a = new-object system.text.asciiencoding
$byte = $a.GetBytes(“$(Get-Date)”)
[void]$udpobject.Send($byte,$byte.length)
#IPEndPoint object will allow us to read datagrams sent from any source.
Write-Verbose “Creating remote endpoint”
$remoteendpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any,0)

Try {
#Blocks until a message returns on this socket from a remote host.
Write-Verbose “Waiting for message return”
$receivebytes = $udpobject.Receive([ref]$remoteendpoint)
[string]$returndata = $a.GetString($receivebytes)
}

Catch {
If ($Error[0].ToString() -match “\bRespond after a period of time\b”) {
#Close connection
$udpobject.Close()
#Make sure that the host is online and not a false positive that it is open
If (Test-Connection -comp $c -count 1 -quiet) {
Write-Verbose “Connection Open”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “UDP”
$temp.Open = “True”
$temp.Notes = “”
}
Else {
<#
It is possible that the host is not online or that the host is online,
but ICMP is blocked by a firewall and this port is actually open.
#>
Write-Verbose “Host maybe unavailable”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “UDP”
$temp.Open = “False”
$temp.Notes = “Unable to verify if port is open or if host is unavailable.”
}
}
ElseIf ($Error[0].ToString() -match “forcibly closed by the remote host” ) {
#Close connection
$udpobject.Close()
Write-Verbose “Connection Timeout”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “UDP”
$temp.Open = “False”
$temp.Notes = “Connection to Port Timed Out”
}
Else {
$udpobject.close()
}
}
#Merge temp array with report
$report += $temp
}
}
}
}
End {
#Generate Report
$report
}
}

Posted in powershell, scripts | Tagged , , , , | 20 Comments

PowerCLI 4.1 cmdlet poster

Working with a VMWare infrastructure, I have been getting more involved with the PowerCLI snap-in that is available for download to manage our systems.  In case anyone was wondering, you can download and print off a poster listing all of the cmdlets and includes a quick reference guide.

http://blogs.vmware.com/files/powercli-poster.pdf

Download PowerCLI 4.1 from here:

http://communities.vmware.com/community/vmtn/vsphere/automationtools/powercli?source=web&cd=1&sqi=2&ved=0CBMQFjAA&url=http://www.vmware.com/go/powercli&rct=j&q=download%20powercli&ei=FJiFTMSoGsaAlAfEsMWgDw&usg=AFQjCNFddkbqT43ZTSqBGo7UBPzAQnwPPg

Posted in PowerCLI, powershell, VMWare | Tagged , , | 1 Comment