PowerShell Script Watch-SWTOR-Client.ps1

Project Objective:
Monitor Star Wars The Old Republic (SWTOR) client for network problems or disconnects.

Problem to be solved:
At times I am disconnected from the SWTOR servers while flying around and or crafting but still running locally (or sometimes all together). I wrote this script to check and see when I was connected to the server properly and when I wasn’t. I then have the script send me an SMS message when I am not connected. I use SMS instead of normal mail because I am on my computer.

Please note that you will need to edit variables like your mail server and SMS email address, etc.

# # Watch-SWTOR-Client.ps1 # # Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com) # # If you edit please keep my name as an original author and # keep me apprised of the changes, see email address above. # This code may not be used for commercial purposes. # You the executor, runner, user accept all liability. # This code comes with ABSOLUTELY NO WARRANTY. # You may redistribute copies of the code under the terms of the GPL v2. # ----------------------------------------------------------------------- # 2012.03.26 ver 2 # # Summary: # Checks number of connections swtor.exe has established. # Sends an email using gmail in the event that the client has been disconnected. # # ----------------------------------------------------------------------- # General Usage: # Edit the varibles below to specify your mial server, username, password and # where you want to send the mail to. # Start Star Wars The Old Republic, start the script from the PowerShell console. # function Get-NetworkStatistics { # From Shay Levy, PowerShell MVP $properties = 'Protocol','LocalAddress','LocalPort' $properties += 'RemoteAddress','RemotePort','State','ProcessName','PID' netstat -ano | Select-String -Pattern '\s+(TCP|UDP)' | ForEach-Object { $item = $_.line.split(" ",[System.StringSplitOptions]::RemoveEmptyEntries) if($item[1] -notmatch '^\[::') { if (($la = $item[1] -as [ipaddress]).AddressFamily -eq 'InterNetworkV6') { $localAddress = $la.IPAddressToString $localPort = $item[1].split('\]:')[-1] } else { $localAddress = $item[1].split(':')[0] $localPort = $item[1].split(':')[-1] } if (($ra = $item[2] -as [ipaddress]).AddressFamily -eq 'InterNetworkV6') { $remoteAddress = $ra.IPAddressToString $remotePort = $item[2].split('\]:')[-1] } else { $remoteAddress = $item[2].split(':')[0] $remotePort = $item[2].split(':')[-1] } New-Object PSObject -Property @{ PID = $item[-1] ProcessName = (Get-Process -Id $item[-1] -ErrorAction SilentlyContinue).Name Protocol = $item[0] LocalAddress = $localAddress LocalPort = $localPort RemoteAddress =$remoteAddress RemotePort = $remotePort State = if($item[0] -eq 'tcp') {$item[3]} else {$null} } | Select-Object -Property $properties } } } do { Start-Sleep -s 60 $count=0 $date=Get-Date $swtorNetStat=Get-NetworkStatistics | Where-Object {$_.ProcessName -eq 'swtor'} | Where-Object {$_.State -eq 'ESTABLISHED'} | Format-Table $count=$swtorNetStat.count #$swtorNetStat if ($count -ge 6) {write-host "Status at" $date" : PASSED"} } while ($count -ge 6) write-host "Status at" $date" : FAILED" $EmailUser="USERNAME" $EmailPassword="PASSWORD" $EmailFrom="USERNAME@gmail.com" $Arry_EmailTo="##########@txt.att.net"

$SMTPServer = "smtp.gmail.com"

$SMTPPort=587

[string]$computername=$env:computername $EmailSubj='SWTOR is not connected on ' + $computername $EmailBody='SWTOR is not connected on ' + $computername + ' at ' + $date # From Christian @ StackOverflow.com $SMTPClient = New-Object Net.Mail.SMTPClient( $SmtpServer, $SmtpPort ) $SMTPClient.EnableSSL = $true $SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $EmailUser, $EmailPassword ); # From Core @ StackOverflow.com $emailMessage = New-Object System.Net.Mail.MailMessage $emailMessage.From = $EmailFrom foreach ( $recipient in $Arry_EmailTo ) { $emailMessage.To.Add( $recipient ) } $emailMessage.Subject = $EmailSubj $emailMessage.Body = $EmailBody $SMTPClient.Send( $emailMessage )

PowerShell Script Watch-Exchange-Queues.ps1

Project Objective:
Monitor Exchange 2010 as well as Exchange 2003 message queues. This script can be deployed in a multiple scenarios with our without a Nagios or other monitoring enviroment.

Problem to be solved:
Increased monitoring of Exchange Server message queues. Get notified when messages are not leaving message queues.

Suggestions:
Monitor Exchange 2010 with native EMS Get-Queue command. – REJECTED, Too slow for monitoring system.
Monitor Exchange 2003 with previous VisualBasic Script check_msmq.wsf – REJECTED, One ring to rule them all!

#
# Watch-Exchange-Queues.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2011.08.31 ver 3
#
# Summary:
# Checks number of messages in Exchange 2003 or 2010 message queues. If warning or
# critical thresholds are reached number of messages are outputted.
# -----------------------------------------------------------------------
# General Usage:
#    This script can be edited and or parameters can be passed to enable
#    email alerts, to whom, from whom, using what server, etc.
#     Examples:    
#        .\Watch-Exchange-Queues.ps1
#        .\Watch-Exchange-Queues.ps1 -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local
#
# Scheduled Task Usage
#    To run this script as a scheduled task create a .bat .cmd file
#    As indicated above you can either pass the needed parameters or
#    edit Watch-Exchange-Queues.ps1 itself. 
#    Example of .bat or .cmd file:
#        powershell -command "& '.\Watch-Exchange-Queues.ps1' -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local"
#
# Nagios Usage:
#    For Nagios NRPE/NSClient++ usage add the following line to the 
#    NSC.ini file after placing this script in Scripts subdirectory.
#    check_exch_mq=cmd /c echo scripts\Watch-Exchange-Queues.ps1; exit($lastexitcode) | powershell.exe -command -
#    NOTE: The trailing - is required.
# -----------------------------------------------------------------------
# Notes:
#    You may have asked "Why not use a more 'native' method to view the queue in Exchange 2010?"
#     Example: Get-ExchangeServer | where {$_.isHubTransportServer -eq $true} | get-queue | where {$_.MessageCount -gt 0} | measure-object MessageCount -max
#    Because the above requires the Exchange Managment Shell be loaded.
#     The shell loading is time consuming and thus the doesn't lend itself to a Nagios checks.
#    IF you want to go the 'native' route I suggest making a Scheduled Task then monitoring the tasks.
# -----------------------------------------------------------------------

# Optional Parameters and Editable Settings Used to Send E-mail Alert
Param(
    [string]$From = 'noreply@domain.ext',
    [string]$To = 'someone@domain.ext',
    [string]$Server = 'smtp.domain.ext',
    [int]$Port = 25,
    [string]$Username,
    [string]$Password,
    [switch]$email = $false,
    [switch]$SSL = $false
)

# Static Parameters
[int]$WarningLevel = 10
[int]$CriticalLevel = 20
[int]$ResultError = 0
[string]$computername=$env:computername


function Send-EmailMessage {
    param([string]$EmailSubj=$Results, [string]$EmailBody=$Results)
    $EmailMessage.Subject = $EmailSubj
    $EmailMessage.Body = $EmailBody
    $SMTPClient.Send( $EmailMessage )
}

# Exchange 2010 Check
$isHubTransportServer=(Test-Path "HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\HubTransportRole")
if ($isHubTransportServer) {
    $MessagesQueued=get-wmiobject -query "select MessagesQueuedForDelivery from Win32_PerfFormattedData_MSExchangeTransportQueues_MSExchangeTransportQueues"
    $Messages=$MessagesQueued.MessagesQueuedForDelivery
    if ($Messages) {
        if ($Messages -lt $WarningLevel) {
            $Results = 'No Alert. Number of messages in queue on '+$computername+': ' +$Messages
        }
        if ($Messages -gt $WarningLevel) {
            $ResultError=1
            $Results = 'WARNING ALERT! Number of messages in queue on '+$computername+': ' +$Messages
        }
        if ($Messages -gt $CriticalLevel) {
            $ResultError=2
            $Results = 'CRITICAL ALERT! Number of messages in queue on '+$computername+': ' +$Messages
        }
    }
    Else {
        $ResultError=1
        $Results = 'WARNING ALERT! Message Queue UNAVAILABLE on ' +$computername
    }
}

# Exchange 2003 (If no information or errors from above then check)
if (!($Results)) {
    $isExchange2003Server=get-wmiobject -query "Select Name From Win32_Service Where Name='MSExchangeSA'"
    if ($isExchange2003Server) {
        $ExchangeQueues=get-wmiobject -Namespace "root\cimv2\Applications\Exchange" -Query "SELECT NumberOfMessages FROM ExchangeQueue"
        foreach ($ExchangeQueue in $ExchangeQueues) {
            if (!($Messages)) { $Messages=$ExchangeQueue.NumberOfMessages  } 
            ELSE { $Messages=$Messages + $ExchangeQueue.NumberOfMessages }
        }

        if ($Messages) {
            if ($Messages -lt $WarningLevel) {
                $Results = 'No Alert. Number of messages in queue on '+$computername+': ' +$Messages
            }
            if ($Messages -gt $WarningLevel) {
                $ResultError=1
                $Results = 'WARNING ALERT! Number of messages in queue on '+$computername+': ' +$Messages
            }
            if ($Messages -gt $CriticalLevel) {
                $ResultError=2
                $Results = 'CRITICAL ALERT! Number of messages in queue on '+$computername+': ' +$Messages
            }
        }
        Else {
            $ResultError=1
            $Results = 'WARNING ALERT! Message Queue UNAVAILABLE on ' +$computername
        }
    }
    Else {
        $Results='No Alert. System is not an Exchange 2003 or 2010 Server with SMTP Message Queues.'
    }
}

if ($email) {
    $SMTPClient = New-Object Net.Mail.SMTPClient($Server, $Port)  
    if (($Username) -and ($Password)) { $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password) }
    if ($SSL) { $SMTPClient.EnableSSL = $true }
    $EmailMessage = New-Object System.Net.Mail.MailMessage
    $EmailMessage.From = $From
    $EmailMessage.To.Add( $To )
}

Switch ($ResultError) {
    default {
        write-host $Results
        exit 0
    }

    1 {
        write-host $Results
        if ($email) { Send-EmailMessage }
        exit 1
    }

    2 {
        write-host $Results
        if ($email) { Send-EmailMessage }
        exit 2
    } 
}

PowerShell Script Watch-MSSQL.ps1

Project Objective:
Monitor remote connection to Microsoft SQL Server can be deployed in a multiple scenarios.

REQUIRED:
Requires a local SQL user account to be used with SQL Authentication. Local account must have CONNECT permissions on each database.

Problem to be solved:
All too often I see people just check to see IF a MSSQL server is answering on its port as a way of determining it is online. Some others have the MSSQL server query itself locally which is a great first step but if your SQL server is in production and its primary use is to serve queries originating from other systems than THAT should be your test not that it can just answer a query locally.

Future Versions:
I’d like to add the SMTP auth ability, when I get around to it.

Notes:

At the moment there is no error detection built in for the email send. Also, note that the email’s subject and body are the same content. Long story short I need the script now!

#
# Watch-MSSQL.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2011.08.31 ver 2
#
# Summary:
# Sends a remote SQL query to Microsoft SQL server databases.
# Can be configured to send an email in non-Nagios environments. 
#
# REQUIRED:
# Requires a local SQL user account to be used with SQL Authentication. 
# Local account must have CONNECT permissions on each database.
#    In Query Editor, enter the following Transact-SQL command: 
#        CREATE LOGIN <login name> WITH PASSWORD = '<password>' ; GO
#        USE <database>; GRANT CONNECT TO <login name> ; GO
#     From: http://msdn.microsoft.com/en-us/library/aa337562.aspx
#          http://msdn.microsoft.com/en-us/library/ms178569.aspx
#     
# -----------------------------------------------------------------------
# General Usage:
#    This script can be edited and or parameters can be passed to enable
#    email alerts, to whom, from whom, using what server, etc.
#     Examples:    
#        .\Watch-MSSQL.ps1 -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local
#
# Scheduled Task Usage
#    To run this script as a scheduled task create a .bat .cmd file
#    As indicated above you can either pass the needed parameters or
#    edit Watch-MSSQL.ps1 itself. 
#    Example of .bat or .cmd file:
#        powershell -command "& '.\Watch-MSSQL.ps1' -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local"
#
# Nagios Usage:
#    For Nagios NRPE/NSClient++ usage add the following line to the 
#    NSC.ini file after placing this script in Scripts subdirectory.
#    check_mssqlquery=cmd /c echo scripts\Watch-MSSQL.ps1; exit($lastexitcode) | powershell.exe -command -
#    NOTE: The trailing - is required.
# -----------------------------------------------------------------------
# Notes:
#    At the moment there is no error detection built in for the email send.
#    There is also no smpt auth. I'll put that in at a later time.
#     Also, note that the email's subject and body are the same content,
#        This is due to me removing the email fuctionality and errors messages
#        then later adding the email fuctionality back only.
# -----------------------------------------------------------------------

Param(
    $Debug=$False,
    [string]$From = 'noreply@domain.ext',
    [string]$To = 'someone@domain.ext',
    [string]$Server = 'smtp.domain.ext',
    $email=$false
)

# Editable Enviroment Settings
[string]$SQLServer='sql.domain.ext'
[int]$SQLPort=1433
[string]$Username='local_sql_useranme'
[string]$password='password'
$Databases=@(
    'database0',
    'database1';
)

# Static Parameters
[string]$Query = "SELECT DB_NAME() AS DataBaseName"
[string]$computername=$env:computername 

function Required-SnapIns {
    try {
        Add-Pssnapin SqlServerProviderSnapin100 -ErrorAction Stop
        Add-Pssnapin SqlServerCmdletSnapin100 -ErrorAction Stop
        return $true
    } catch {
        [string]$ErrorString = [string]$_.Exception.Message
        if ($ErrorString.contains("already added")) {
            return $true
        } else {
            Write-Host $_.Exception.Source,":", $ErrorString
            return $false
        }
    }
}

function Get-SQLQuery {
    Param([string]$SQLServer,[string]$Database,[string]$Query)
    if (($username) -and ($password)) {
        $Results = Invoke-SQLCmd -ServerInstance $SQLServer -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query -Username $Username -Password $Password
    }
    ELSE {
        $Results = Invoke-SQLCmd -ServerInstance $SQLServer -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query
    }
    return $Results
}

function Test-Port{
    Param([string]$server,$port,$timeout=300)    
    $ErrorActionPreference = "SilentlyContinue"
    $tcpclient = new-Object system.Net.Sockets.TcpClient
    $iar = $tcpclient.BeginConnect($server,$port,$null,$null)
    $wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
    if(!$wait)
    {
        $tcpclient.Close()
        Return $false
    }
    else
    {
        $error.Clear()
        $tcpclient.EndConnect($iar) | out-Null
        Return $true
        $tcpclient.Close()
    }
}

# Debug
if (!$Debug) { $ErrorActionPreference="SilentlyContinue" }

if ($email) {
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($Server)
    $msg.From = $From
    $msg.To.Add($To)
}

$Install=Required-SnapIns
if (!$Install){
    $Results = "ERROR: Required SnapIns not present."
    write-host $Results
    if ($email) {
        $msg.Subject = $Results
        $msg.Body = $Results
        $smtp.Send($msg)
    }
    exit 1
}

$SQLServerUp1=Test-Port $SQLServer $SQLPort
if (!$SQLServerUp1){
    $SQLServerUp2=Test-Port $SQLServer $SQLPort
    if (!$SQLServerUp2){
        $Results="CRITICAL ERROR: SQL Server " + $SQLServer + " did not respond on port " + $SQLPort + " from " + $computername
        write-host $Results
        if ($email) {
            $msg.Subject = $Results
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 2 
    }
}

ForEach ($Database in $Databases) {
    $QueryResults=Get-SQLQuery $SQLServer $Database $Query
    if (!$QueryResults){
        if ($Results) {
            $Results=$Results + " and " + $Database
        }
        ELSE {
            $Results="CRITICAL ERROR: Database(s) Offline: " + $Database
        }
    }
    
    if ($CheckedDatabases) {
    $CheckedDatabases=$Database + ", " + $CheckedDatabases
    }
    ELSE {
        [string]$CheckedDatabases=$Database
    }
}

if ($Results) {
    write-host $Results
    if ($email) {
        $msg.Subject = $Results
        $msg.Body = $Results
        $smtp.Send($msg)
    }
    exit 2
}
ELSE {
    write-host "All database(s) are online. Database(s) checked:" $CheckedDatabases
    exit 0
}

PowerShell Script Install-ExchPrereqs.ps1

Project Objective:
Reduce time spend installing Exchange 2010 prerequisites for various roles.

Problem to be solved:
Current method of setting prerequisites involves looking up a webpage. http://technet.microsoft.com/en-us/library/bb691354.aspx#WS08R2 This way you can save a few minutes per machine.

#***********************************************************************
# "Install-ExchPrereqs.ps1"
#
# Written by Aaron Wurthmann (aaron <AT> wurthmann <DOT> com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor,runner,user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# Prerequisite:
# Written for Exchange 2010 prerequisites for Windows Server 2008 R2
# -----------------------------------------------------------------------
# 2010.10.21 ver 1.0
#
# Summary:
# Installs Exchange 2010 prerequisites for Windows Server 2008 R2 uses
# required roll option to determine which prerequisites to install.
#
# From: http://technet.microsoft.com/en-us/library/bb691354.aspx#WS08R2
#************************************************************************

Param([string]$switch = 'help')

$Computer='.'
$ExpectedOS='Microsoft Windows Server 2008 R2*'

Function Get-Some-Help {
    write-host ''
    write-host 'Installs Exchange 2010 Prerequisites for Windows Server 2008 R2'
    write-host ''
    write-host 'Usage: Install-Exch-Prereqs.ps1 <options>' 
    write-host ''
    write-host 'Options:'
    write-host '    chtmu    Client Access, Hub Transport, Mailbox, and Unified Messaging server roles prerequisites'
    write-host '    cthm    Client Access, Hub Transport, and Mailbox server roles prerequisites'
    write-host '    cht    Client Access, and Hub Transport server roles prerequisites'
    write-host '    htm    Hub Transport, and Mailbox server roles prerequisites'
    write-host '    cm    Client Access, and Mailbox server roles prerequisites'
    write-host '    c    Client Access server role prerequisites'
    write-host '    ht    Hub Transport server role prerequisites'
    write-host '    m    Mailbox server role prerequisites'
    write-host '    u    Unified Messaging server role prerequisites'
    write-host '    et    Edge Transport role prerequisites'
    write-host ''
    exit(1)
}

Function Get-OS-Version {
    $OS=Get-WMIobject Win32_OperatingSystem -Comp $Computer | Select Caption,ServicePackMajorVersion
    If ($OS.Caption -notlike $ExpectedOS) {
        Get-Some-Help
    }
}

Get-OS-Version

Import-Module ServerManager

Switch ($switch) {
    
    #Default Get Some Help
    default {Get-Some-Help}
    
    #Client Access, Hub Transport, Mailbox, and Unified Messaging server roles.
    chtmu {
        Set-Service NetTcpPortSharing -StartupType Automatic
        Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy,Desktop-Experience -Restart
    }
    
    #Client Access, Hub Transport, and Mailbox server roles.
    cthm {
    Set-Service NetTcpPortSharing -StartupType Automatic
    Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -Restart
    }

    #Client Access and Hub Transport server roles.
    cht {
    Set-Service NetTcpPortSharing -StartupType Automatic
    Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -Restart
    }

    #Hub Transport and Mailbox server roles.
    htm {Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server -Restart}

    #Client Access and Mailbox server roles.
    cm {
    Set-Service NetTcpPortSharing -StartupType Automatic
    Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -Restart
    }

    #Client Access server role only.
    c {
    Set-Service NetTcpPortSharing -StartupType Automatic
    Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -Restart
    }

    #Hub Transport or the Mailbox server role.
    ht {Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server -Restart}
    m {Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server -Restart}

    #Unified Messaging server role only.
    u {Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Desktop-Experience -Restart }

    #Edge Transport server role only.
    et {Add-WindowsFeature NET-Framework,RSAT-ADDS,ADLDS -Restart}
}

PowerShell Script Send-Email.ps1

Project Objective:
Send simple e-mail with or without credentials, with or without SSL encryption.

Problem to be solved:
My current scripts do not account for SMTP authorization being required on send. This script can be used as a standalone script or with minor changes a function.

Future Versions:
Since the primary purpose of this script was versatility I need to re-add the ability to send attachments. I removed the incomplete functionality from because at the moment I do not need to send attachments.

Notes:

This script (or one like it) was originally written by Rodney Fisk – xizdaqrian@gmail.com with aid from: Christian @ StackOverflow.com and Core @ StackOverflow.com

#
# Send-Email.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2011.07.05 ver 2.0
#
# Summary:
# Send simple e-mail with or without credentials, with or without SSL encryption.
# The primary purpose of this script was versatility.
# -----------------------------------------------------------------------
# Usage:
# This script can be used as a standalone script or with minor changes a function.
# Example:
# Send-Email.ps1 -from aaron.wurthmann@domain.local -to aaron_wurthmann@domain.local -Subject "Test Subject #42" -Body "Nice body!" -Server smtp.domain.local -Port 587 -User USERNAME -Pass PASSWORD -SSL True
# -----------------------------------------------------------------------
# Orgin:
# This script (or one like it) was originally written by Rodney Fisk - xizdaqrian@gmail.com
#     with aid from: Christian @ StackOverflow.com and Core @ StackOverflow.com
# -----------------------------------------------------------------------



# Mandatory = $true means that the parameter is required and if not included you will be prompted for it.
# Alias is just that, an alias to a parameter verses using the actual parameter name. I.G. "From" vs. "EmailFrom"
param(
    [Parameter(Mandatory = $true,
        Position = 0,
        ValueFromPipelineByPropertyName = $true)]
        [Alias('From')]
    [String]$emailFrom,

    [Parameter(Mandatory = $true,
        Position = 1,
        ValueFromPipelineByPropertyName = $true)]
        [Alias('To')]
    [String[]]$emailRecipients,

    [Parameter(Mandatory = $true,
        Position = 2,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'Subject' )]
    [String]$emailSubject,

    [Parameter(Mandatory = $true,
        Position = 3,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'Body' )]
    [String]$emailBody,

    [Parameter(Mandatory = $true,
        Position = 4,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'Server' )]
    [String]$SMTPServer,

    [Parameter(Mandatory = $false,
        Position = 5,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'Port' )]
    [Int]$SMTPPort=25,
    
    [Parameter(Mandatory = $false,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'User' )]
    [string]$SMTPUser,

    [Parameter(Mandatory = $false,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'Password' )]
    [string]$SMTPPass,
    
    [Parameter(Mandatory = $false,
        ValueFromPipelineByPropertyName = $true)]
        [Alias( 'SSL' )]
    $SMTPSSL
)

#Create an SMTP client using .NET
$SMTPClient = New-Object Net.Mail.SMTPClient( $SmtpServer, $SmtpPort ) 

#If SSL is needed per parameter above enable SSL on the SMTP client
if ($SMTPSSL) { $SMTPClient.EnableSSL = $true }
#If a Username and Password have been added per parameter above add to SMTP client
if ($SMTPUser -and $SMTPPass) { $SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $SMTPUser, $SMTPPass ) }

#Create new message to be sent
$emailMessage = New-Object System.Net.Mail.MailMessage
#Add who will send the message to the message envelope
$emailMessage.From = $emailFrom
#Add Recipient(s) to the message envelope (Note that this method adds all recipients to the same message)
foreach ( $emailRecipient in $emailRecipients ) { $emailMessage.To.Add( $emailRecipient ) }

#Add Subject to message envelope
$emailMessage.Subject = $emailSubject
#Add Body to message envelope
$emailMessage.Body = $emailBody

#Using SMTP client send email message
$SMTPClient.Send( $emailMessage )
#Clear email message (helps clean up memory use)
$emailMessage.Dispose()

PowerShell Profile Microsoft.PowerShell_profile.ps1

Notes:
This is my current profile, it is very simple at the moment.

function prompt {
    $cwd = (get-location).Path

    [array]$cwdt=$()
    $cwdi=-1
    do {
        $cwdi=$cwd.indexofany(”\\”,$cwdi+1)
        [array]$cwdt+=$cwdi} until($cwdi -eq -1)

        if ($cwdt.count -gt 3) {
            $cwd = $cwd.substring(0,$cwdt[0]) + “\..” + $cwd.substring($cwdt[$cwdt.count-3])
    }

    ” $cwd>_ ”
}
# The above sets prompt to the current drive letter, immediate sub directory and current directory.
#     Example: C:\..\drivers\etc>_ 

Import-Module Pscx #-arg ~\Pscx.UserPreferences.ps1

PowerShell Script Watch-EventLogs.ps1

Project Objective:
Monitor event logs with script that can be deployed in a multiple scenarios.

Problem to be solved:
A few of the existing Nagios scripts or commands that have similar functionality either do not provide the verbose output that this script has or they do have an expectable method for adding exceptions.

Future Versions:
I’d like to add the SMTP auth ability. I’m also considering an all in one Application, System log script.

Notes:
This script is not limited to the Application and System logs, you can use it to check any Windows event log. Note that I changed the verb from Test to Watch. I think Watch better fits the description, I may go back and change other scripts to reflect this.

#
# Watch-EventLogs.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2011.06.27 ver 1.7
#
# Summary:
# Checks for recent* Warning and Error messages in the System OR Applicaiton event logs.
# Default checks System logs, use -logname Application, to check Application logs
#
# *Recent: Uses registry key to determine when the last check was made.
# -----------------------------------------------------------------------
# General Usage:
#    This script can be edited and or parameters can be passed to enable
#    email alerts, to whom, from whom, using what server, etc.
#     Examples:    
#        .\Watch-EventLogs.ps1 -Logname Application
#        .\Watch-EventLogs.ps1 -Logname System
#        .\Watch-EventLogs.ps1 -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local
#
# Scheduled Task Usage
#    To run this script as a scheduled task create a .bat .cmd file
#    As indicated above you can either pass the needed parameters or
#    edit Watch-EventLogs.ps1 itself. 
#    Example of .bat or .cmd file:
#        powershell -command "& '.\Watch-EventLogs.ps1' -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local"
#
# Nagios Usage:
#    For Nagios NRPE/NSClient++ usage add the following line to the 
#    NSC.ini file after placing this script in Scripts subdirectory.
#    check_sysevents=cmd /c echo scripts\Watch-EventLogs.ps1; exit($lastexitcode) | powershell.exe -command -
#    check_appevents=cmd /c echo scripts\Watch-EventLogs.ps1 -logname Application; exit($lastexitcode) | powershell.exe -command -
#    NOTE: The trailing - is required.
# -----------------------------------------------------------------------
# Notes:
#    At the moment there is no error detection built in for the email send.
#    There is also no smpt auth. I'll put that in at a later time.
# -----------------------------------------------------------------------

# Parameters and Editable Settings
Param(
    [int]$ResultWarning = 0,
    [int]$ResultError = 0,
    [string]$From = "noreply@domain.ext",
    [string]$To = "someone@domain.ext",
    [string]$Server = "smtp.domain.ext",
    [string]$Logname = "System",
    $email=$false
)

$IgnoreSources=@(
    'Print',
    'DnsApi',
    'Some Source',
    'Some other Source';
)

$IgnoreEvendID=@(
    '42424242',
    '69696969';
)
# End Editable Section


[string]$computername=$env:computername 
$RegKey='HKLM:\SYSTEM\CurrentControlSet\Services\NRPE_NT'
$RegEntry=$Logname+'_Log_Check'
$Date=Get-Date

if(!(Test-Path $RegKey)) {New-Item -Path $RegKey}
$NRPE=Get-ItemProperty -Path $RegKey
if (!($NRPE.$RegEntry)) {
    $CreateRegEntry=New-ItemProperty -Path $RegKey -Name $RegEntry -PropertyType String -Value $Date
    if ($CreateRegEntry) {
        $NRPE=Get-ItemProperty -Path $RegKey
    }
    ELSE {
        write-host 'FATAL ERROR:' $RegKey'\'$RegEntry 'was not created.'
        exit 2
        
    }
}
$ExecDate=$NRPE.$RegEntry

$Properties='EntryType','Message','Source','TimeWritten','EventID'
$LogEntries=Get-EventLog -Logname $Logname -EntryType Error,Warning -After $ExecDate | 
    Where {$IgnoreSources -notcontains $_.Source -and $IgnoreEvendID -notcontains $_.EventID} | 
    Select-Object -Property $Properties

$Date=Get-Date
Set-ItemProperty -Path $RegKey -Name $RegEntry -Value $Date
    
if ($LogEntries) {
    ForEach ($LogEntry in $LogEntries) {
        $EntryType=$LogEntry.EntryType.ToString()
        $Message=$LogEntry.Message.Substring(0,76).TrimEnd().ToString()+'...'
        $Source=$LogEntry.Source.ToString()
        $TimeWritten=$LogEntry.TimeWritten.ToString()
        $EventID=$LogEntry.EventID.ToString()
         
         
        if ($EntryType -eq 'Error') {
            $ResultError=2
            if ($CriticalResults) {
                $CriticalResults=@"
$EntryType 
Event ID: $EventID
$Message
Source: $Source
At: $TimeWritten

$CriticalResults
"@
            }
            ELSE {
                $CriticalResults = @"
$EntryType
Event ID: $EventID 
$Message
Source: $Source
At: $TimeWritten
"@
            }
        }
        ELSE {
            if ($EntryType -eq 'Warning') {
                $ResultWarning=1
                if ($WarningResults) {
                    $WarningResults=@"
$EntryType
Event ID: $EventID 
$Message
Source: $Source
At: $TimeWritten

$WarningResults
"@
                }
                ELSE {
                    $WarningResults = @"
$EntryType
Event ID: $EventID 
$Message
Source: $Source
At: $TimeWritten
"@
                }
            }
        }
    }
}

if ($email) {
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($Server)
    $msg.From = $From
    $msg.To.Add($To)
}

[int]$ResultTotal=$ResultWarning + $ResultError
$Results= @"
$Logname Entries:

$CriticalResults

$WarningResults
"@

Switch ($ResultTotal) {
    default {
        write-host 'No Errors or Warnings were found in the' $Logname 'event logs as of' $Date
        exit 0
    }

    1 {
        write-host $Results
        if ($email) {
            $msg.Subject = 'WARNING: Warning messages were found in the ' +$Logname+ ' event logs on ' + $computername + ' at ' + $Date
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 1
    }

    2 {
        write-host $Results
        if ($email) {
            $msg.Subject = 'CRITICAL: Error messages were found in the ' +$Logname+ ' event logs on ' + $computername + ' at ' + $Date
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 2
    } 

    3 {
        write-host $Results
        if ($email) {
            $msg.Subject = 'CRITICAL: Error and Warning messages were found in the ' +$Logname+ ' event logs on ' + $computername + ' at ' + $Date
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 2
    } 
}

PowerShell Script Test-Volume-Space.ps1

Project Objective:
Monitor available volume space with single script that can be deployed in a multiple scenarios.

Problem to be solved:
Running out of disk space on a server is not fun and users noticing before you do is even less fun, but Nagios and or NRPE isn’t always deployed in every environment. This script is an effort to bridge the gap between central and local monitoring.

Future Versions:
I’d like to add the SMTP auth ability as well as Event Log entries.

Notes:
v1.5 contains suggested edits from Stephen Mills and bug fix.

#
# Test-Volume-Space.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2011.05.12 ver 1.5
#
# Summary:
# Checks for disk percent usage on all Windows partitions/logical disks.
# Can be configured to send an email in non-Nagios environments. 
# -----------------------------------------------------------------------
# General Usage:
#    This script can be edited and or parameters can be passed to enable
#    email alerts, to whom, from whom, using what server, etc.
#     Examples:    
#        .\Test-Volume-Space.ps1 -WarningLevel 70
#        .\Test-Volume-Space.ps1 -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local
#
# Scheduled Task Usage
#    To run this script as a scheduled task create a .bat .cmd file
#    As indicated above you can either pass the needed parameters or
#    edit Test-Volume-Space.ps1 itself. 
#    Example of .bat or .cmd file:
#        powershell -command "& '.\Test-Volume-Space.ps1' -email True -From foobar@null.local -To administrator@null.local -Server smtp.null.local"
#
# Nagios Usage:
#    For Nagios NRPE/NSClient++ usage add the following line to the 
#    NSC.ini file after placing this script in Scripts subdirectory.
#    check_services=cmd /c echo scripts\Test-Volume-Space.ps1; exit($lastexitcode) | powershell.exe -command -
#    NOTE: The trailing - is required.
# -----------------------------------------------------------------------
# Notes:
#    At the moment there is no error detection built in for the email send.
#    There is also no smpt auth. I'll put that in at a later time.
#
#     Lines with ### are from previous version of script where "Win32_LogicalDisk"
#    was used instead of "Win32_Volume". The latter captures disks
#    mounted as folders. Thank you "Stephen Mills" for your insight.
#    
#    In addition to Stephen Mills' suggestions this version properly
#    handles the event where one drive is hitting the warning level and 
#    another is hitting the critical level. I knew there was a reason 
#    I wanted to leave that logic in from my vbscript.
# -----------------------------------------------------------------------

# Parameters and Editable Settings
Param(
    [int]$WarningLevel = 80,
    [int]$CriticalLevel = 90,
    [string]$From = 'noreply@domain.ext',
    [string]$To = 'someone@domain.ext',
    [string]$Server = 'smtp.domain.ext',
    $email=$false
)

# Volume Names to Ignore
$Ignore=@(
    'Backups',
    'Recovery',
    'Reserved';
)

# Static Parameters
[int]$ResultWarning = 0
[int]$ResultError = 0
[string]$CriticalResults = ''
[string]$WarningResults = ''
[string]$Results = ''
[string]$computername=$env:computername 


# Get local disks that are not in the ignore list
$Volumes=Get-WMIObject Win32_Volume -filter "DriveType=3"  | where {$Ignore -notcontains $_.Label}
###$Volumes=Get-WMIObject Win32_LogicalDisk -filter "DriveType=3" | where {$Ignore -notcontains $_.VolumeName}

if ($Volumes) {
    ForEach ($Volume in $Volumes) {
        ###[string]$DeviceID=$Volume.DeviceID
        [string]$Name=$Volume.Name
        [int]$FreeGBs=$Volume.FreeSpace/1073741824
        ###[int]$SizeGBs=$Volume.Size/1073741824
        [int]$SizeGBs=$Volume.Capacity/1073741824
        [int]$UsedGBs=$SizeGBs-$FreeGBs
        [int]$PerUsed=$UsedGBs/$SizeGBs*100
        ###[string]$VolumeInfo = $DeviceID + " Used " + $PerUsed + " GB of " + $SizeGBs + " GB"
        [string]$VolumeInfo = $Name + " Used " + $PerUsed + " GB of " + $SizeGBs + " GB"
        
        if ($PerUsed -gt $CriticalLevel) {
            $ResultError=2
            if ($CriticalResults) {
                $CriticalResults=$VolumeInfo + " and " + $CriticalResults
            }
            ELSE {
                $CriticalResults = $VolumeInfo + " exceeding the Critical Level of " + $CriticalLevel +"% used on " + $computername
            }
        }
        ELSE {
            if ($PerUsed -gt $WarningLevel) {
                $ResultWarning=1
                if ($WarningResults) {
                    $WarningResults=$VolumeInfo + " and " + $WarningResults
                }
                ELSE {
                    $WarningResults = $VolumeInfo + " exceeding the Warning Level of " + $WarningLevel +"% used on " + $computername
                }
            }
        }
        if ($AllVolumeInfo) {
            $AllVolumeInfo=$VolumeInfo + ", " + $AllVolumeInfo
        }
        ELSE {
            [string]$AllVolumeInfo=$VolumeInfo
        }
    }
}

if ($email) {
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($Server)
    $msg.From = $From
    $msg.To.Add($To)
}


[int]$ResultTotal=$ResultWarning + $ResultError
$Results=$CriticalResults + " " + $WarningResults

Switch ($ResultTotal) {
    default {
        write-host 'All drive usage is healthy. Drive(s) checked:' $AllVolumeInfo
        exit 0
    }

    1 {
        write-host $Results
        if ($email) {
            $msg.Subject = 'WARNING: Hard Drive Usage Has Reached Warning Level on ' + $computername
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 1
    }

    2 {
        write-host $Results
        if ($email) {
            $msg.Subject = 'CRITICAL: Hard Drive Usage Has Reached Critical Level on ' + $computername
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 2
    } 

    3 {
        write-host $Results
        if ($email) {
            $msg.Subject = 'CRITICAL: Multiple Hard Drives Have Reached Critical or Warning Levels'
            $msg.Body = $Results
            $smtp.Send($msg)
        }
        exit 2
    } 
}

PowerShell Script Connect-RDP.ps1

Project Objective:
Reconnect to systems after they’ve been rebooted. Replace the age old “Ping till you get a reply” method and have a little fun while you wait (listening to the Super Mario Brothers theme).

Problem to be solved:
The problem with the “Ping till you get a reply” method is that Remote Desktop is one if not these last service to start on a Windows Server. Simply pinging a host just means its on the network, you still have a good minute or two (or more) before the host will answer to a Remote Desktop request.

Future Versions:
I’m releasing/posting this incomplete. I really wanted to do more with it. Play other songs, make the the music faster after a time period and more. However as luck would have it, I just don’t have the time, and since it is functional I might as well post it.

Notes:
This script started out as a replacement for my rdp.cmd script that used the “Ping till you get a reply” method then waited two minutes and connected via Remote Desktop. Then I learned how to make PC speaker sounds in PowerShell and got carried away.

 

#
# Connect-RDP.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2011.03.18 ver 3.0
#
# Summary:
# Reconnect to systems after they’ve been rebooted. 
# Replaces the age old “Ping till you get a reply” method and plays the
# Super Mario Brothers theme while you wait.
#
# Current version has limited error and syntax checking.
# -----------------------------------------------------------------------
# Usage: Connect-RDP.ps1 <host or IP address>
# 
# -----------------------------------------------------------------------
# Notes:
# This script started out as a replacement for my rdp.cmd script that 
# used the “Ping till you get a reply” method then waited two minutes and 
# connected via Remote Desktop. Then I learned how to make sounds in PowerShell.
# -----------------------------------------------------------------------



Param([string]$strhost="127.0.0.1",$limit=1,$total=18)

function Get-IP {
    $IPAddress=$null
    $chkresult=[System.Net.IPAddress]::tryparse($strhost,[ref]$IPAddress) -and $strhost -eq $IPaddress.tostring()
    if ($chkresult -eq $false){
    $strhost=Get-Lookup
    }
}

function Get-Lookup{
    [string]$lookup=nslookup $strhost | Select-String "Name"
    if (!$lookup){
        write-host 'ERROR:' $strhost 'not found'
        exit
    }
    $result=$lookup.Split(" ")
    if($result){
        return $result[-1]
    }
    Else{
        write-host 'ERROR:' $strhost 'not found'
        exit
    }
}

function Test-Port{
    Param([string]$srv=$strhost,$port=3389,$timeout=300)    
    $ErrorActionPreference = "SilentlyContinue"
    $tcpclient = new-Object system.Net.Sockets.TcpClient
    $iar = $tcpclient.BeginConnect($srv,$port,$null,$null)
    $wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
    if(!$wait)
    {
        $tcpclient.Close()
        Return $false
    }
    else
    {
        $error.Clear()
        $tcpclient.EndConnect($iar) | out-Null
        Return $true
        $tcpclient.Close()
    }
}

function Play-MarioInto {
    [console]::beep($E, $SIXTEENTH)
    [console]::beep($E, $EIGHTH)
    [console]::beep($E, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($C, $SIXTEENTH)
    [console]::beep($E, $EIGHTH)
    [console]::beep($G, $QUARTER)
}

function Play-Mario1-1 {
    [console]::beep($C, $EIGHTHDOT)
    [console]::beep($GbelowC, $SIXTEENTH)
    Start-Sleep -m $EIGHTH
    [console]::beep($EbelowG, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($A, $EIGHTH)
    [console]::beep($B, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($Asharp, $SIXTEENTH)
    [console]::beep($A, $EIGHTH)
    [console]::beep($GbelowC, $SIXTEENTHDOT)
    [console]::beep($E, $SIXTEENTHDOT)
    [console]::beep($G, $EIGHTH)
    [console]::beep($AHigh, $EIGHTH)
    [console]::beep($F, $SIXTEENTH)
    [console]::beep($G, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($E, $EIGHTH)
    [console]::beep($C, $SIXTEENTH)
    [console]::beep($D, $SIXTEENTH)
    [console]::beep($B, $EIGHTHDOT)
    [console]::beep($C, $EIGHTHDOT)
    [console]::beep($GbelowC, $SIXTEENTH)
    Start-Sleep -m $EIGHTH
    [console]::beep($EbelowG, $EIGHTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($A, $EIGHTH)
    [console]::beep($B, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($Asharp, $SIXTEENTH)
    [console]::beep($A, $EIGHTH)
    [console]::beep($GbelowC, $SIXTEENTHDOT)
    [console]::beep($E, $SIXTEENTHDOT)
    [console]::beep($G, $EIGHTH)
    [console]::beep($AHigh, $EIGHTH)
    [console]::beep($F, $SIXTEENTH)
    [console]::beep($G, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($E, $EIGHTH)
    [console]::beep($C, $SIXTEENTH)
    [console]::beep($D, $SIXTEENTH)
    [console]::beep($B, $EIGHTHDOT)
    Start-Sleep -m $EIGHTH
    [console]::beep($G, $SIXTEENTH)
    [console]::beep($Fsharp, $SIXTEENTH)
    [console]::beep($F, $SIXTEENTH)
    [console]::beep($Dsharp, $EIGHTH)
    [console]::beep($E, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($GbelowCSharp, $SIXTEENTH)
    [console]::beep($A, $SIXTEENTH)
    [console]::beep($C, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($A, $SIXTEENTH)
    [console]::beep($C, $SIXTEENTH)
    [console]::beep($D, $SIXTEENTH)
    Start-Sleep -m $EIGHTH
    [console]::beep($G, $SIXTEENTH)
    [console]::beep($Fsharp, $SIXTEENTH)
    [console]::beep($F, $SIXTEENTH)
    [console]::beep($Dsharp, $EIGHTH)
    [console]::beep($E, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($CHigh, $EIGHTH)
    [console]::beep($CHigh, $SIXTEENTH)
    [console]::beep($CHigh, $QUARTER)
    [console]::beep($G, $SIXTEENTH)
    [console]::beep($Fsharp, $SIXTEENTH)
    [console]::beep($F, $SIXTEENTH)
    [console]::beep($Dsharp, $EIGHTH)
    [console]::beep($E, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($GbelowCSharp, $SIXTEENTH)
    [console]::beep($A, $SIXTEENTH)
    [console]::beep($C, $SIXTEENTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($A, $SIXTEENTH)
    [console]::beep($C, $SIXTEENTH)
    [console]::beep($D, $SIXTEENTH)
    Start-Sleep -m $EIGHTH
    [console]::beep($Dsharp, $EIGHTH)
    Start-Sleep -m $SIXTEENTH
    [console]::beep($D, $EIGHTH)
    [console]::beep($C, $QUARTER)
}

#Set Speed and Tones
if($CHigh -eq $null) {
    $WHOLE = 2200
    $HALF = $WHOLE / 2
    $QUARTER = $HALF / 2
    $EIGHTH = $QUARTER / 2
    $SIXTEENTH = $EIGHTH / 2
    $EIGHTHDOT = $EIGHTH + $SIXTEENTH
    $QUARTERDOT = $QUARTER + $EIGHTH
    $SIXTEENTHDOT = $SIXTEENTH + ($SIXTEENTH / 2)


    $REST = 37
    $EbelowG = 164
    $GbelowC = 196
    $GbelowCSharp = 207
    $A = 220
    $Asharp = 233
    $B = 247
    $C = 262
    $Csharp = 277
    $D = 294
    $Dsharp = 311
    $E = 330
    $F = 349
    $Fsharp = 370
    $G = 392
    $Gsharp = 415
    $AHigh = 440
    $CHigh = 523
}


# Check to see if entry is a valid IPv4 address. 
#    If not treat as a host.
#        if host, do an nslookup before attemting connect.
#            If fail throw error.
Clear-Host
Get-IP
Play-MarioInto

$SecondsTotal = $total * 17

#write-host "Testing:" $strhost

while ($totalCt -lt $total) {
    $totalCt++
    $SecondsCt = $totalct * 17
    $SecondsRemaining = $SecondsTotal - $SecondsCt
    $PercentComplete = $SecondsCt / $SecondsTotal * 100
    $PercentLeft = 100 - $PercentComplete
    Write-Progress -Activity "Checking RDP on $strhost..." -PercentComplete $PercentLeft -currentOperation "Checking status of tcp port 3389 on $strhost" -SecondsRemaining $SecondsRemaining -Status "Will give up after 00:05:00"
    #write-host "Total Count:" $totalct
    $count=0
    [string]$strresult=Test-Port
    while ($strresult -eq $true) {
        $count++
        Write-Progress -Activity "Checking RDP on $strhost..." -Completed -Status "Has answered."
        #write-host "Answer Count:" $count
        $SecondsLimit = $limit * 10
        $SecondsCt = $count * 10
        $SecondsRemaining = $SecondsLimit - $SecondsCt
        $PercentComplete = $SecondsCt / $SecondsLimit * 100
        Write-Progress -Activity "$strhost is ready for RDP" -PercentComplete $PercentComplete -currentOperation "$strhost has replied" -SecondsRemaining $SecondsRemaining -Status "Will connect after $SecondsLimit seconds"
        [string]$strresult=Test-Port
        if ($count -ge $limit) {
            Write-Progress -Activity "$strhost is ready for RDP" -Completed -Status "Connecting..."
            mstsc.exe /v:$strHost
            exit
        }
    Start-Sleep -s 9
    }
Play-Mario1-1
}

PowerShell Script Test-Automatic-Services.ps1

Project Objective:
Nagios/NRPE plugin to test if all services that are set to Automatic are indeed running (ignoring a list of services that are deemed ‘OK’). If not runing, attempt to restart the service, if the restart fails send a critical error, if the restart is successful send a warning error.

Problem to be solved:
Existing check_services.wsf Nagios plugin doesn’t have an editable array.

Suggestions:
Add array to existing wsf/vbsript plugin – REJECED
If I’m going to do that much re-writing I’d rather convert the script to PowerShell, also I appreciate how arrays are done in PowerShell more than in vbscript.

Future Versions:
I’m considering adding or replacing the error returns with Event log entries instead, though presumably they should be there already.

Notes:
There are some services that you may prefer to set to Manual instead of Automatic and vice versa instead of adding them to the ignore list.

#
# Test-Automatic-Services.ps1
#
# Written by Aaron Wurthmann (aaron (AT) wurthmann (DOT) com)
#
# If you edit please keep my name as an original author and
# keep me apprised of the changes, see email address above.
# This code may not be used for commercial purposes.
# You the executor, runner, user accept all liability.
# This code comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the code under the terms of the GPL v2.
# -----------------------------------------------------------------------
# 2010.11.09 ver 2.0
#
# Summary:
# Checks services set to Automatic and insures they are running.
# Ignores an array of services such as Performance Logs and Alerts
# which are set to Automatic but turns themselves off.
#
# If an Automatic service is not Running and not in the Ignore array
# an attempt to restart the service is made. If the service is restarted
# a Warning is returned. If the service could not be restarted a
# Critical error is returned.
# -----------------------------------------------------------------------
# Usage:
# This script does not require any input parameters.
#    For Nagios NRPE/NSClient++ usage add the following line to the
#    NSC.ini file after placing this script in Scripts subdirectory.
#    check_services=cmd /c echo scriptsTest-Automatic-Services.ps1; exit($lastexitcode) | powershell.exe -command -
#    NOTE: The trailing - is required.
# -----------------------------------------------------------------------
# Orgin:
# This script (or one like it) was originally written by ronald van vugt
#     (ronald.van.vugt@vanderlet.nl)
# I took the vbscriptwsf version that he wrote and converted it to
# PowerShell while adding an array of ignored services and making other
# slight improvements such as adjusting the WMI query to only return
# stopped services.
# -----------------------------------------------------------------------
# Notes:
# Unlike the majority of my scripts this script has rather verbose
# comments in it. This is both to pay homage to the original author as
# well as to aid others with learning PowerShell. The original version
# of this script, the vbscript/wsf version was a vbscript learning
# experience for myself and the basis of my vbscripts to follow.
# -----------------------------------------------------------------------

# Varibles used to caluclate number and type of errors if any.
[int]$intResultWarning = 0
[int]$intResultError = 0
[int]$intResultTotal = 0

# List of Services to Ignore.
$Ignore=@(
    'Microsoft .NET Framework NGEN v4.0.30319_X64',
    'Microsoft .NET Framework NGEN v4.0.30319_X86',
    'Multimedia Class Scheduler',
    'Performance Logs and Alerts',
    'SBSD Security Center Service',
    'Shell Hardware Detection',
    'Software Protection',
    'TPM Base Services';
)

# Get list of services that are not running, not in the ignore list and set to automatic
$Services=Get-WmiObject Win32_Service | Where {$_.StartMode -eq 'Auto' -and $Ignore -notcontains $_.DisplayName -and $_.State -ne 'Running'}

# If any services were found fitting the above description...
if ($Services) {
    # Loop through each service in services
    ForEach ($Service in $Services) {
        # Attempt to restart the service
        $err = $Service.StartService()
        # Pause for 1 second
        Start-Sleep -s 1
        # Re-Get the Service information in order to recheck its status
        $StoppedService=Get-Service -Displayname $Service.Displayname
        # If the service failed to restart...
        If ($StoppedService.Status -ne 'Running') {
            # Set the error level to 2 (critical)
            $intResultError = 2
            # If this is not the first recorded error amend the error text
            if ($strResultError) {
                $strResultError=$strResultError + ', ' + $Service.Displayname
            }
            # If this is the first or only error set error text
            ELSE {
                $strResultError = 'Services failed after restart: ' + $Service.Displayname
            }
        }
        ELSE {
            # If the service restarted set the warning error level to 1 (warning)
            $intResultWarning = 1
            # If this is not the first recorded error amend the error text
            if ($strResultWarning) {
            $strResultWarning=$strResultWarning + ', ' + $Service.Displayname
            }
            # If this is the first or only error set error text
            ELSE {
                $strResultWarning = 'Services restarted: ' + $Service.Displayname
            }
        }
        # Clear the StoppedService varible
        if ($StoppedService) {Clear-Variable StoppedService}
    }
}

# Add the warning error (0 or 1) to the critical error (0 or 2)
$intResultTotal=$intResultWarning + $intResultError

# Using the sum of the warning errors to the critical errors select the appropriate response
Switch ($intResultTotal) {
    # Default/no errors
    default {
        write-host 'All automatic started services are running'
        exit 0
    }
    # Warning error(s) only
    1 {
        write-host $strResultWarning
        exit 1
    }
    # Critical error(s) only
    2 {
        write-host $strResultError
        exit 2
    }
    # Critical and Warning errors
    3 {
        write-host $strResultError
        write-host $strResultWarning
        exit 2
    }
}