Guest Blog on Hey, Scripting Guy! on Querying for X509 Certificates

A month ago, I was asked by Ed Wilson if I wanted to write a guest blog on the Hey, Scripting Guy blog. Naturally, I said yes to this because this an opportunity to write for a great guy like Ed.

I decided to write about working with pki certificates using some .NET classes and reading certificates on both local and remote computers.

The link to the blog is right here.

The function that I wrote for this blog is here.

Enjoy!!

Posted in News, powershell | Tagged , , , , | 1 Comment

Retrieving Weather Information From A Web Service Provider

I noticed on my twitter feed about a PowerTip from powershell.com that showed you how to retrieve the weather information from a given web service. This is a pretty cool 3 lines of code that used the New-WebServiceProxy cmdlet that connects to the web service allows you to create a proxy object to manage the web service.

In short, a web service is defined as being:

A Web service is an XML-based program that exchanges data over a network, particularly over the Internet.

Here is the code example that was provided from powershell.com’s power tips section.

$a = New-WebServiceProxy 'http://www.webservicex.net/globalweather.asmx?WSDL'
$a.GetCitiesByCountry('United States')
$a.GetWeather('San Francisco','United States')

Capture

The GetCitiesByCountry() method will list all of the possible cities available to query in a given county. In this case, all of the cities in the United States was listed.

The GetWeather() method requires a string value for City and Country and returns the weather information. Now, the format returned is a string format that displays the xml content and isn’t the most presentable format. This is easily resolved by using [xml], which is an accelerator for the System.Xml.XmlDocument class to convert it into a more user friendly format. But just adding the [xml] type at the beginning of the code will not do anything.

[xml]$a.GetWeather('San Francisco','United States')

Capture

Ok, so now that we have it converted into an xml object, we just need to view the CurrentWeather property.

([xml]$a.GetWeather('San Francisco','United States')).CurrentWeather

Capture

Now that’s more like it. You can now easily view all of the weather information for a given city without trying to sift through all of the xml syntax.

Of course I couldn’t resist making this into an Advanced Function to call whenever I needed to.  I called it Get-Weather and with this function, you have two possible ways of using it.  You can use Get-Weather –Country “United States” –ListCities to list all of the available cities in the United States or any other respective country. To get the weather information, you use Get-Weather –Country “United States” –City “Omaha” and with that, you will get the weather information for the city of Omaha, Nebraska.

Capture

The link http://www.webservicex.net/ws/default.aspx contains many other services besides the weather.  I would encourage you to check these out and have fun making your own different functions or code snippets that use these other services and share them with others.

Script Download

Script Repository

PoshCode

Code

Function Get-Weather { 
<#   
.SYNOPSIS   
   Display weather data for a specific country and city. 
.DESCRIPTION 
   Display weather data for a specific country and city. There is a possibility for this to fail if the web service being used is unavailable. 
.PARAMETER Country 
    URL of the website to test access to. 
.PARAMETER ListCities 
    Use the currently authenticated user's credentials   
.PARAMETER City 
    Used to connect via a proxy          
.NOTES   
    Name: Get-Weather 
    Author: Boe Prox 
    DateCreated: 15Feb2011  
.LINK  
    http://www.webservicex.net/ws/default.aspx 
.LINK  
    https://boeprox.wordpress.com        
.EXAMPLE   
    Get-Weather -Country "United States" -ListCities 
     
Description 
------------ 
Returns all of the available cities that are available to retrieve weather information from. 
.EXAMPLE   
    Get-Weather -Country "United States" -City "San Francisco" 
     
Description 
------------ 
Retrieves the current weather information for San Francisco 
 
#>  
[cmdletbinding( 
    DefaultParameterSetName = 'Weather', 
    ConfirmImpact = 'low' 
)] 
    Param( 
        [Parameter( 
            Mandatory = $True, 
            Position = 0, 
            ParameterSetName = '', 
            ValueFromPipeline = $True)] 
            [string]$Country, 
        [Parameter( 
            Position = 1, 
            Mandatory = $False, 
            ParameterSetName = 'listcities')] 
            [switch]$ListCities, 
        [Parameter( 
            Mandatory = $False, 
            ParameterSetName = '')] 
            [string]$City                        
                         
        ) 
Begin { 
    $psBoundParameters.GetEnumerator() | % {   
        Write-Verbose "Parameter: $_"  
        }      
    Try { 
        #Make connection to known good weather service 
        Write-Verbose "Create web proxy connection to weather service" 
        $weather = New-WebServiceProxy 'http://www.webservicex.net/globalweather.asmx?WSDL' 
        } 
    Catch { 
        Write-Warning "$($Error[0])" 
        Break 
        }         
    } 
Process { 
    #Determine if we are only to list the cities for a given country or get the weather from a city 
    Switch ($PSCmdlet.ParameterSetName) { 
        ListCities { 
            Try { 
                #List all cities available to query for weather 
                Write-Verbose "Listing cities in country: $($country)" 
                (([xml]$weather.GetCitiesByCountry("$country")).newdataset).table | Sort City | Select City 
                Break 
                } 
            Catch { 
                Write-Warning "$($Error[0])" 
                Break 
                } 
            } 
        Weather { 
            Try { 
                #Get the weather for the city and country 
                Write-Verbose "Getting weather for Country: $($country), City $($city)" 
                ([xml]$weather.GetWeather("$city", "$country")).CurrentWeather 
                } 
            Catch { 
                Write-Warning "$($Error[0])" 
                } 
            } 
        } 
    } 
End { 
    Write-Verbose "End function, performing clean-up" 
    Remove-Variable city -Force 
    Remove-Variable country -Force 
    }    
}
Posted in powershell, scripts | Tagged , , | 1 Comment

Using PowerShell to Query Web Site Information

In my last post, I showed you how to use the Test-Connection cmdlet to test your internet access.  In this post, I can show you how to use Net.WebRequest or the Net.WebClient to send a request to website and verify if you have internet access or not. There is more you can do with these other than just testing Internet access or testing that a website is currently up and running, but that is beyond the scope of that I am going to show you here.

Net.WebClient Class

The first class I will show is the Net.WebClient class to access a web page.  Using this class and its associated methods will actually download the source page of the website.  If you also look at the methods, you can see methods for downloading files, download data, uploading data and files. Again, this is more than what I will go into at this time, but still, it does provide some pretty cool things to do with this class.

First off, lets create the object using the Net.WebClient class and view those methods.

$web = New-Object Net.WebClient
$web | Get-Member

Capture

As you can see, there are a lot of methods and even some events that you can leverage when using this class. For the sake of this post, I will be going into using the DownloadString() method to use in testing a connection to a web site.

Using this, I will use the DownloadString() method to download the webpage and display it in a powershell console. Keep in mind this will be displayed in a pretty un-user friendly format, but that is ok because we are only concerned whether we can actually access the site or not.

$web.DownloadString("http://www.bing.com")

Capture

Holy cow! That is a lot of wild output, isn’t it? As you can see, the entire bing.com webpage has been downloaded and is now being displayed in the PowerShell console.  Just for the sake of something a little bit smaller, I will run this against microsoft.com as well to show.

Capture

Ok, that’s better. Again, just be seeing this information shows us that we are able to connect to the internet, and not only that we are able to access the webpage without any issues.

So we know what happens when a site is active or our internet connection is active, but what happens if the connection is down?

Try {
	$web.DownloadString("https://hereisasite.net")
	} 
Catch {
	Write-Warning "$($error[0])"
	}

Capture

Knowing that you can use Try/Catch when making the web site connection, you can then use looping (Do Until, Do While, While) to continue to attempt a connection until it is able to do so, and then send some sort of notification when successful.

Begin {
    $web = New-Object System.Net.WebClient
    $flag = $false
    }
Process {
    While ($flag -eq $false) {
        Try {
            $web.DownloadString("https://hereisasite.net")
            $flag = $True
            }
        Catch {
            Write-host -fore Red -nonewline "Access down..."
            }
        }
    }    
End {
    Write-Host -fore Green "Access is back"
    }

Capture

Had I used a legit site and killed my connection and then brought it back online, you would have seen the green text stating the access was back.  However, I was listening to the PowerScripting Podcast and didn’t want to miss out on listening to it.

One last item on using this class for your connecting and verifying needs. This doesn’t really apply to testing the connection but is still pretty cool. This involves shows how many bytes a the webpage that you are downloading is.

Let’s re-look at bing.com and find out how large their page is…

"{0} bytes" -f ($web.DownloadString("http://bing.com")).length.toString("###,###,##0")

Capture

As you can see, it is roughly 27KB in size for bing.com. Again, pretty cool if you wanted to know just how big a page is that you are downloading to your browser.

Net.WebRequest

Using this class, I will show you how to get a response from a web server hosting a site. Unlike the Net.WebClient class, you will not be able to download the site page. However, with this class, you can get a response code and also see what type of web server is being used to host the site.

First we will create the object that we can then use to get a response back from the web site.  Since this class does not have a constructor we can use like the previous class, we will use a static method available from this class to create the object. Using the Create method also requires that we input the web site name as well.

$webRequest = [net.WebRequest]::Create("http://microsoft.com")
$webRequest | gm

Capture

There are a few methods here to use, but the main one that we will use is GetResponse(). Using this method will return back data about the website such as the type of web server being used to host the site, the status code, description and even the size of the webpage, much like I should you could do using the Net.WebClient class and converting the output to a string and getting the length.

$webrequest.GetResponse()

Calling the GetResponse() method shows you the following:

IsMutuallyAuthenticated : False
Cookies                 : {}
Headers                 : {VTag, Accept-Ranges, Content-Length, Cache-Control…}
ContentLength           : 1020
ContentEncoding         :
ContentType             : text/html
CharacterSet            : ISO-8859-1
Server                  : Microsoft-IIS/7.5
LastModified            : 3/16/2009 3:35:26 PM
StatusCode              : OK
StatusDescription       : OK
ProtocolVersion         : 1.1
ResponseUri             :
http://www.microsoft.com/
Method                  : GET
IsFromCache             : False

I am not much of a web person, from some of the information given, I can see that microsoft.com homepage is approximately 1KB in size and that the web server hosting this page is IIS 7.5.  One thing to note is that the StatusCode says OK.  If you look at the type of object this is, you will see that it is a System.Net.HttpStatusCode object. Clicking on the link, you can see that there many members of this class that relate to different codes that a web site may return.

You can convert this object into an integer to get the code by casting it as an integer.

(($webRequest.GetResponse()).Statuscode) -as [int]

PS C:\Users\boe> (($webRequest.GetResponse()).Statuscode) -as [int]
200

I would recommend doing this method as the StatusDescription matches the StatusCode and there is no need to have the exact same output and they can compliment each other.

Assuming my network connection was down or the site itself was down, you could use a Try/Catch statement to catch the error, and in turn like using the Net.WebClient class, perform a loop to monitor that site.

Capture

I have written a couple of advanced functions that utilize both of these .Net classes:

Get-Website  which is a wrapper for Net.WebClient

Test-Website which is a wrapper for Net.WebRequest

Code

Get-WebPage:

Script Repository

CodePlex

Get-WebSite:

Script Repository

CodePlex

function Get-WebPage {
<#  
.SYNOPSIS  
   Downloads web page from site.
.DESCRIPTION
   Downloads web page from site and displays source code or displays total bytes of webpage downloaded
.PARAMETER Url
    URL of the website to test access to.
.PARAMETER UseDefaultCredentials
    Use the currently authenticated user's credentials  
.PARAMETER Proxy
    Used to connect via a proxy
.PARAMETER Credential
    Provide alternate credentials 
.PARAMETER ShowSize
    Displays the size of the downloaded page in bytes                 
.NOTES  
    Name: Get-WebPage
    Author: Boe Prox
    DateCreated: 08Feb2011        
.EXAMPLE  
    Get-WebPage -url "http://www.bing.com"
    
Description
------------
Returns information about Bing.Com to include StatusCode and type of web server being used to host the site.

#> 
[cmdletbinding(
	DefaultParameterSetName = 'url',
	ConfirmImpact = 'low'
)]
    Param(
        [Parameter(
            Mandatory = $True,
            Position = 0,
            ParameterSetName = '',
            ValueFromPipeline = $True)]
            [string][ValidatePattern("^(http|https)\://*")]$Url,
        [Parameter(
            Position = 1,
            Mandatory = $False,
            ParameterSetName = 'defaultcred')]
            [switch]$UseDefaultCredentials,
        [Parameter(
            Mandatory = $False,
            ParameterSetName = '')]
            [string]$Proxy,
        [Parameter(
            Mandatory = $False,
            ParameterSetName = 'altcred')]
            [switch]$Credential,
        [Parameter(
            Mandatory = $False,
            ParameterSetName = '')]
            [switch]$ShowSize                        
                        
        )
Begin {     
    $psBoundParameters.GetEnumerator() | % { 
        Write-Verbose "Parameter: $_" 
        }
   
    #Create the initial WebClient object
    Write-Verbose "Creating web client object"
    $wc = New-Object Net.WebClient 
    
    #Use Proxy address if specified
    If ($PSBoundParameters.ContainsKey('Proxy')) {
        #Create Proxy Address for Web Request
        Write-Verbose "Creating proxy address and adding into Web Request"
        $wc.Proxy = New-Object -TypeName Net.WebProxy($proxy,$True)
        }       
    
    #Determine if using Default Credentials
    If ($PSBoundParameters.ContainsKey('UseDefaultCredentials')) {
        #Set to True, otherwise remains False
        Write-Verbose "Using Default Credentials"
        $wc.UseDefaultCredentials = $True
        }
    #Determine if using Alternate Credentials
    If ($PSBoundParameters.ContainsKey('Credentials')) {
        #Prompt for alternate credentals
        Write-Verbose "Prompt for alternate credentials"
        $wc.Credential = (Get-Credential).GetNetworkCredential()
        }         
        
    }
Process {    
    Try {
        If ($ShowSize) {
            #Get the size of the webpage
            Write-Verbose "Downloading web page and determining size"
            "{0:N0}" -f ($wr.DownloadString($url) | Out-String).length -as [INT]
            }
        Else {
            #Get the contents of the webpage
            Write-Verbose "Downloading web page and displaying source code" 
            $wc.DownloadString($url)       
            }
        
        }
    Catch {
        Write-Warning "$($Error[0])"
        }
    }   
}  

 

function Get-WebSite {
<#  
.SYNOPSIS  
    Retrieves information about a website.
.DESCRIPTION
    Retrieves information about a website.
.PARAMETER Url
    URL of the website to test access to.
.PARAMETER UseDefaultCredentials
    Use the currently authenticated user's credentials  
.PARAMETER Proxy
    Used to connect via a proxy
.PARAMETER TimeOut
    Timeout to connect to site, in milliseconds
.PARAMETER Credential
    Provide alternate credentials              
.NOTES  
    Name: Get-WebSite
    Author: Boe Prox
    DateCreated: 08Feb2011        
.EXAMPLE  
    Get-WebSite -url "http://www.bing.com"
    
Description
------------
Returns information about Bing.Com to include StatusCode and type of web server being used to host the site.

#> 
[cmdletbinding(
	DefaultParameterSetName = 'url',
	ConfirmImpact = 'low'
)]
    Param(
        [Parameter(
            Mandatory = $True,
            Position = 0,
            ParameterSetName = '',
            ValueFromPipeline = $True)]
            [string][ValidatePattern("^(http|https)\://*")]$Url,
        [Parameter(
            Position = 1,
            Mandatory = $False,
            ParameterSetName = 'defaultcred')]
            [switch]$UseDefaultCredentials,
        [Parameter(
            Mandatory = $False,
            ParameterSetName = '')]
            [string]$Proxy,
        [Parameter(
            Mandatory = $False,
            ParameterSetName = '')]
            [Int]$Timeout,
        [Parameter(
            Mandatory = $False,
            ParameterSetName = 'altcred')]
            [switch]$Credential            
                        
        )
Begin {     
    $psBoundParameters.GetEnumerator() | % { 
        Write-Verbose "Parameter: $_" 
        }
   
    #Create the initial WebRequest object using the given url
    Write-Verbose "Creating the web request object"        
    $webRequest = [net.WebRequest]::Create($url)
    
    #Use Proxy address if specified
    If ($PSBoundParameters.ContainsKey('Proxy')) {
        #Create Proxy Address for Web Request
        Write-Verbose "Creating proxy address and adding into Web Request"
        $webRequest.Proxy = New-Object -TypeName Net.WebProxy($proxy,$True)
        }
        
    #Set timeout
    If ($PSBoundParameters.ContainsKey('TimeOut')) {
        #Setting the timeout on web request
        Write-Verbose "Setting the timeout on web request"
        $webRequest.Timeout = $timeout
        }        
    
    #Determine if using Default Credentials
    If ($PSBoundParameters.ContainsKey('UseDefaultCredentials')) {
        #Set to True, otherwise remains False
        Write-Verbose "Using Default Credentials"
        $webrequest.UseDefaultCredentials = $True
        }
    #Determine if using Alternate Credentials
    If ($PSBoundParameters.ContainsKey('Credentials')) {
        #Prompt for alternate credentals
        Write-Verbose "Prompt for alternate credentials"
        $wc.Credential = (Get-Credential).GetNetworkCredential()
        }            
        
    #Set TimeStamp prior to attempting connection    
    $then = get-date
    }
Process {    
    Try {
        #Make connection to gather response from site
        $response = $webRequest.GetResponse()
        #If successful, get the date for comparison
        $now = get-date 
        
        #Generate report
        Write-Verbose "Generating report from website connection and response"  
        $report = @{
            URL = $url
            StatusCode = $response.Statuscode -as [int]
            StatusDescription = $response.StatusDescription
            ResponseTime = "$(($now - $then).totalseconds)"
            WebServer = $response.Server
            Size = $response.contentlength
            } 
        }
    Catch {
        #Get timestamp of failed attempt
        $now = get-date
        #Put the current error into a variable for later use
        $errorstring = "$($error[0])"
        
        #Generate report
        $report = @{
            URL = $url
            StatusCode = ([regex]::Match($errorstring,"\b\d{3}\b")).value
            StatusDescription = (($errorstring.split('\)')[2]).split('.\')[0]).Trim()
            ResponseTime = "$(($now - $then).totalseconds)" 
            WebServer = $response.Server
            Size = $response.contentlength
            }   
        }
    }
End {        
    #Display Report    
    New-Object PSObject -property $report  
    }    
}  
Posted in powershell, scripts | Tagged , , | 38 Comments

Quick Hits: Test Internet Access

A while back I was having all sorts of internet connection issues with my ISP.  The connection would drop and I would have to play the “click refresh” game with my browser and wait until the magical moment when I would have my access back.

So with that, I came up with an idea to monitor my connection to a website that would let me know when that access came back, saving me the time and annoyance of click the refresh button.

I wouldn’t say this is the most practical script, but it was something I decided to do just to kill some time.

I use two main cmdlets to accomplish this task:

Test-Connection with the –count and –quiet parameters

Write-Host with the –foregroundcolor and  -nonewline parameters

Using the –count and –quiet parameters will attempt one try at connecting to the computer, or in this case the website. The –quiet allows me to return a True (if the site is reachable) and a False (if the site is not reachable).

Example

For the sake of demonstration, I am disabling my network connection and using google.com as my test connection site. Now why didn’t I use a site like bing.com or microsoft.com?  Good question! For whatever reason, the Test-Connection fails against either of these sites while google.com returns a positive connection.

Test-InternetConnection -Site google.com -Wait 2

Capture

That’s all there is to it. A date/time stamp is also given when the connection has come back up.

Code

Function Test-InternetConnection {
<#
.SYNOPSIS
    Use this function to test your internet connection and monitor while it is down.
.DESCRIPTION
    Use this function to test your internet connection and monitor while it is down. When the connection is back up, a text notification will show up.
.PARAMETER Site
    Name of the site to use for connection test.
.PARAMETER Wait
    Time to wait before retrying Test-Connection (seconds)
.NOTES
    Author     : Boe Prox
    Created    : 05Feb2011
.LINK
    https://boeprox.wordpress.com
#>
[cmdletbinding(
    DefaultParameterSetName = 'Site'
)]
param(
    [Parameter(
        Mandatory = $True,
        ParameterSetName = '',
        ValueFromPipeline = $True)]
        [string]$Site,
    [Parameter(
        Mandatory = $True,
        ParameterSetName = '',
        ValueFromPipeline = $False)]
        [Int]$Wait
    )
    #Clear the screen
    Clear
    #Start testing the connection and continue until the connection is good.
	While (!(Test-Connection -computer $site -count 1 -quiet)) {
        Write-Host -ForegroundColor Red -NoNewline "Connection down..."
        Start-Sleep -Seconds $wait
		}
    #Connection is good
	Write-Host -ForegroundColor Green "$(Get-Date): Connection up!"
}
Posted in powershell, scripts | Tagged , , | 10 Comments

Quick Hits: Ping Sweep One Liner

So I was curious as to how many active ip addresses I had on my network and didn’t feel like manually typing “ping <ipaddress>” and wait for it to timeout and then “rinse and repeat”.  Along comes Test-Connection and the –quiet  and –count switches that allow me to make one attempt and then return a True/False status on whether the ip is active or not.

I then decided that this would make a great one liner that would list out the IP address I am testing followed by the True/False status. 

As you can see, it’s a pretty simple one liner that can quickly show you what is active.

1..20 | % {"192.168.1.$($_): $(Test-Connection -count 1 -comp 192.168.1.$($_) -quiet)"}

Capture

Posted in powershell | Tagged , , | 3 Comments