Enabling Poweshell ISE for Windows Server 2008 R2

Working with Powershell scripts the last few weeks, I have discovered that the Powershell ISE (Integrated Scripting Environment) isn’t installed by default on many servers. This can easily be added, either by “Add Feature” or by powershell itself. As  old-fashion, hard-core developer, I’m using the command shell 🙂

  1. Open Powershell command shell
  2. Execute following cmdlets.
Import-Module ServerManager 
Add-WindowsFeature PowerShell-ISE

Check eventlog status in powershell

When we monitor servers, we need to get notified if there are new errors and/or warnings in the Windows Eventlog.. Normally, it is the Application event log we check for these errors and warnings. The required functionality is that the script should check for errors and warnings on the current machine and if the number of event exceeds a maximum, the script should send an email to administrator to notify that some further investigation is needed on the server.

Here is the second powershell script I wrote today:

CHECK_EVENT_LOG_STATISTICS.PS1:

param([String]$logname="Application", [Int]$maxEventCount=10)

$since = ((get-date).addDays(-1));

$errwarnlist =  Get-Eventlog -logname $logname -after $since 
			-EntryType Error, Warning
$linecount = $errwarnlist | Measure-Object –Line

$msg = $env:COMPUTERNAME + " " + $logname + " eventlog has " 
       + $linecount.Lines  
       + " errors/warnings since " + $since.ToString("dd.MM.yyy HH:mm") 
       + ". Limit = " + $maxEventCount;

if ($linecount.Lines -gt $maxEventCount)
{
    $xto = john.doe@company.com
    $xfrom = "no-reply@company.com"
    $xsub = $env:COMPUTERNAME + ": " + $logname 
            + " eventlog exceeds limit for errors/warnings";

    Write-host $msg

    Send-MailMessage -To $xto -From $xfrom  
                 -Subject $xsub  -Body $msg 
                 -SmtpServer smtp.company.com
}
else
{
    Write-host $msg
}

Check service status in powershell

This week have been dedicated to baselining and monitoring server state. Our department is mainly monitoring SQL Server, Sharepoint  and Dynamic CRM servers for our customers. Therefore, it is very important to check if services for are running at all time. If they are not running we have to restart them, otherwise out customers will have downtime for the particular service. The powershell script below checks if a service exist and running. If it is not running the script is trying to restart the service. The script will send an email if the servcie is not installed on the server or can not be restarted.

CHECK_SERVICE_STATE.PS1:
param([String]$svcname="")

if ($svcname.Trim().Length -eq 0)
{
    Write-Host "Invalid service name" ;
    return ;
}

$svc = get-service $svcname -ErrorAction SilentlyContinue;
if ($svc -eq $null)
{
    $xto = "jon.doe@company.com"
    $xfrom = "no-reply@company.com"
    $xsub = $env:COMPUTERNAME + ": " + $svcname + " service error";
    $msg = $env:COMPUTERNAME + ": " + $svcname + " service does not exist";
    Write-host $msg
    Send-MailMessage -To $xto -From $xfrom  -Subject $xsub  
                     -Body $msg -SmtpServer smtp.company.com
    return;
}

$sts = $svc | Select Status;
if ($sts.Status.ToString() -eq "Stopped")
{
    Write-Host "Service " $svcname  " is STOPPED ==> trying to restart";
    Restart-Service $svcname ;
    $svc = get-service $svcname -ErrorAction SilentlyContinue;
    if ($svc -ne $null)
    {
        $sts = $svc | Select Status ;
        if ($sts.Status.ToString() -eq "Stopped")
        {
            $xto = "jon.doe@company.com"
            $xfrom = "no-reply@company.com"
            $xsub = $env:COMPUTERNAME + ": " + $svcname + " service error";
            $msg = $env:COMPUTERNAME + ": " + $svcname 
                          + " service could not be restarted";
            Write-host $msg
            Send-MailMessage -To $xto -From $xfrom  -Subject $xsub  
                             -Body $msg -SmtpServer smtp.company.com
            return
        }

        Write-Host $svcname " status = " $sts.Status.ToString();
    }
}
else
{
    Write-Host "Service " $svcname " is still RUNNING";
}

Calculate total and iteration elapsed time in Powershell

When you are executing long-running scripts you probably want to know how long time each part of the script is taking to execute, and the total run time of the script. The demo script below shows how to use the Get-Date and Get-Random CmdLets.

When calculating elapsed time the substraction will result in a TimeSpan database like the one in C#.

$script:startTime = Get-Date

function GetElapsedTime([datetime]$starttime) 
{
    $runtime = $(get-date) - $starttime
    $retStr = [string]::format("{0} sec(s)", $runtime.TotalSeconds)
    $retStr
}

write-host "Script Started at $script:startTime"
for ($i=1; $i -lt 10; $i++) 
{
    $iterTime = Get-Date ;
    get-process | out-null
    $waitsecs = Get-Random -minimum 1 -maximum 5
    sleep $waitsecs
    $elapsed = GetElapsedTime $iterTime ;
    write-host "   Iteration Time: " $elapsed ;
}

write-host "Script Ended at $(get-date)"
$elapsed = GetElapsedTime $script:startTime
write-host "Total Elapsed Time: " $elapsed;

Happy coding…

SQL Server – sending email tsql + powershell

Today, I wanted to send an email when a long-running script completed successfully. The SQL server was already configured correctly with the Database Mail Configuration Wizard, so I just had to add similar code as code below to send the mail:

EXEC msdb.dbo.sp_send_dbmail
    @recipients = 'john.doe@someplace.com',
    @body = 'The custom script was successfully completed',
    @subject = 'Automated Success Message' ;

In addition, yesterday I had to send email from a powershell script to notify owner of Sharepoint sites. Here is my send_mail function used from powershell:

function send_email ([string]$emailTo, [string]$emailFrom, 
			[string]$emailSubject, [string]$emailBody)
{
    $emailSmtpServer = "smtp.company.com"
    $emailSmtpServerPort = "25"
    $emailSmtpUser = "COMPANY\johndoe"
    $emailSmtpPass = "johndoe"

    $emailMessage = New-Object System.Net.Mail.MailMessage
			( $emailFrom , $emailTo )
    $emailMessage.IsBodyHtml = $true
    $emailMessage.Subject = $emailSubject
    $emailMessage.Body = $emailBody 

    $SMTPClient = New-Object System.Net.Mail.SmtpClient
			( $emailSmtpServer , $emailSmtpServerPort )
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential
			( $emailSmtpUser , $emailSmtpPass );

    $SMTPClient.Send( $emailMessage )
 }

Off course, I need to rework the security here and not hard code the password, but for testing purpose, this worked smoothly yesterday.

Happy emailing 🙂