Rehash: Testing Web Pages Once More

I seem to be rehashing a lot of stuff.  The reason is that I’m trying to capture what I actually find useful, and hope this blog will capture processes that I may use later.  Many of these processes start from copy-pasting items I’ve already posted and either building on them or Lego-ing the together.  Apologies for the redundant content, though I feel the glue code makes it worth posting

 

function Get-ActiveDirectoryObjects {
<#
.synopsis
Get object data from Active Directory.

.description
Get object data from Active Directory, similar to dsquery.exe, but using LDAP.

.parameter Pattern
ADSI 'Name' DirectorySearch filter.  Defaults to '*'.  Values passed in will be bracketed by '*'

.paramter ObjectCategory
ADSI 'ObjectCategory' DirectorySearch filter.  Defaults to $null, which will generate a warning.
#>

     param ( 
         [String]$Pattern = '*',
         [string]$ObjectCategory = $null
     );

     if ($ObjectCategory) {
         $directorySearcher = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$env:userDnsDomain"); 
         $directorySearcher.PageSize = 1000; 
         $directorySearcher.Filter = "(&(objectCategory=$ObjectCategory)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(name=*${Pattern}*))"; 
         $directorySearcher.FindAll();
     } else {
         Write-Warning "-ObjectCategory not specified, required.";
     } # if ($ObjectCategory
} # function

function Get-ActiveDirectoryComputerNames {
<#
.synopsis
Get computer data from Active Directory.

.description
Get object data from Active Directory, similar to dsquery.exe, but using LDAP.

.parameter Pattern
ADSI 'Name' DirectorySearch filter.  Defaults to '*' (returns all computers known to AD).

.parameter AsObject
Return data as System.DirectoryServices.SearchResult objects.  Default is to return only the DnsHostname (the FQDN).

#>

     param ( 
         [String[]]$Pattern = '*',
         [switch]$AsObject
     );

     $Pattern | % { 
         $myPattern = $_ -replace "\..*";
         Get-ActiveDirectoryObjects -Pattern $myPattern -ObjectCategory computer; 
     } |  %{
         if ($AsObject) {
             $_;
         } else {
             $_.Properties.Item('DnsHostName') | % { $_.ToString().ToLower(); }
         } # if
     } # $Pattern | % { ...
} # function

function Test-WebServer {
<#
.synopsis
Test response from webservers, ignoring certificate errors.

.description
Test response from webservers, ignoring certificate errors, allowing for splatting of server names.

.parameter ComputerName
Server(s) to test.  Defaults to none.

.parameter Url
URL to test.  This overrides the behavior of -ComputerName, -Path, and -Protocol.  Instead of synthesizing URLs from the values for those parameters, the function only tests the specified URL.

.parameter Path
The path portion of the URL.  For the URL https://ServerName/Path/To/File, the string 'Path/To/File' is the value for -Path.

.parameter Protocol
The protocol portion of the URL.  For the URL https://ServerName/Path/To/File, the string 'https' is the value for -Protocol.

.parameter Pattern
An expected substring or Regular Expression expected in the web page's source code. Defaults to $null, which means any content returned is a success.

.parameter Timeout
Time in milliseconds, for both the ping and the attempt to connect to the web server.

#>

    param (
        [Parameter( ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )][String[]]$ComputerName = @(),
        [string]$Url,
        [String]$Path,
        [String]$Protocol = 'https',
        [string]$Pattern = $null,
        [int]$Timeout = 2000
    )
   
    begin {
        [Net.ServicePointManager]::ServerCertificateValidationCallback = { $true };
        $webClient = New-Object System.Net.WebClient;
       
        $ping = New-Object system.net.NetworkInformation.Ping;
        $Protocol = $Protocol -replace '[:/]';

        if ($Url) { [String[]]$ComputerName = $Url -replace ".*//" -replace "/.*" }

    } # begin
   
    process {
        $ComputerName | % {
       
            foreach ($myComputer in (Get-ActiveDirectoryComputerNames -Pattern $_)) {
           
                if (!$Url) { $Url = "${Protocol}://$myComputer/$Path"; }
                Write-Progress (Get-Date) $Url;
                Write-Verbose $Url;
               
                # create and pre-populate return object
                $object = 1 | Select-Object -Property ComputerName, URL, Status;
                $object.ComputerName = $myComputer;
                $object.URL= $Url;
                $object.Status = 'ERROR';
               
                if ($ping.Send($myComputer, $Timeout).Status -eq 'Success') {
                    $webRequest = [System.Net.WebRequest]::Create($Url);
                    $webRequest.Timeout = $Timeout;
                   
                    try { $response = $webRequest.GetResponse(); }
                    catch { $object.Status = 'FAILED_TO_CONNECT'; }
                    finally { $response.Close(); }
                   
                    if ($response.StatusCode -eq 'OK') {
                   
                        try { $string = $webClient.DownloadString($Url); }
                        catch { $object.Status = 'FAILED_TO_CONNECT'; }
                       
                        if ($string) {
                           
                            if ($Pattern) {
                               
                                if ($string -match $Pattern) {
                                    $Object.Status = 'PASS';
                                } else {
                                    $Object.Status = 'FAILED_TO_MATCH';
                                } # if ($string -match
                               
                            } else {
                                $Object.Status = 'PASS';
                            } # if ($pattern
                           
                        } else {
                            $object.Status = 'FAILED_TO_DOWNLOAD';
                        } # if ($string
                    } else {
                        $object.Status = "FAILED_STATUS($($response.StatusCode))";
                    } # if ($response.StatusCode
                } else {
                    $object.Status = 'FAILED_TO_PING';
                 } # if ($ping.Send

                 $object;

             } # foreach ($myComputer
            
             if (!$object) { Write-Warning "Unable to process -ComputerName $ComputerName"; }
         } # $ComputerName | % { ....
     } # process
} # function