Read in a date and time from a string

I have a log file that I need to put some alerting onto and would like to use Powershell.

The log file has multiple line in all in this format.
(ART)End Processing Autoroutines (12/06/15 15:50:47)

I have so far used the below to get the last line in the file.
get-content C:\Karl\ATM-E-DocsEmailproatm.log -tail 1

I would like to read in the date and time part of the string to compare the difference with the current date and time. Then perform some actions.

I am having trouble separating the date from the string to assign to a variable.

Any help would be appreciated.

Thanks in advance.
Karl

If you know that your date/time will always be in that US format (mm/dd/yy hh:mm:ss), then you can use a combination of regex and casting:

$x = '(ART)End Processing Autoroutines (12/06/15 15:50:47)'
New-TimeSpan -Start (Get-Date) -End ($x.Split('(',3)[-1]).TrimEnd(')')

I have no idea of your skill level, so it’s possible this might hurt your brain. In case it does, then let’s walk though how I came up with this.

  1. I assigned $x the string you’re collecting from your log file.
PS C:\> $x = '(ART)End Processing Autoroutines (12/06/15 15:50:47)'
  1. I wanted to start splitting up the string, and did so at the left parens. I indicated to the .Split() method to make three substrings, so I could get the date and time on a line by itself. For fun, try changing 3, to 1 and 2 to see the difference.
PS C:\> $x.Split('(',3)

ART)End Processing Autoroutines
12/06/15 15:50:47)
  1. Next, I grabbed the last element, or index, so it would only give me the last substring.
PS C:\> $x.Split('(',3)[-1]
12/06/15 15:50:47)
  1. When I just had the date and time, I used the .TrimEnd() method to remove the ending right paren.
PS C:\> ($x.Split('(',3)[-1]).TrimEnd(')')
12/06/15 15:50:47
  1. In the end, I stuffed all this together as the value for the New-TimeSpan’s -End parameter and it returned the comparison.

Edit: Or just use Dave’s suggestion. By the way, all those double quotes are supposed to be single. I’m not sure why that happened.

Thanks guys, that make perfect sense now. I was trying to use trim to do it but knew there would be a different method.

Just learning the basics of powershell at the moment by watching the VMA powershell jumpstart.

Hi Guys

I was wondering if you could take a look at my code and let me know if I could have improved it? As I am just starting out, getting the syntax correct was my main hurdle here.

Any feedback would be appreciated.

 
#Read last line from the Log file
$Logfile ="C:\karl\ATM-E-DocsReceiptsproatm.log"
$Server ="Proclaim-ATM2"
$ATMName ="Edocs Reciepts ATM"
$to = "Karl@helphire.co.uk"
$from = "ATMMonitor@helphire.co.uk"
$subject = "Critical Message from node: $server"
$x = get-content $Logfile -tail 1



#If last line contains specific words exit the script
if ($x -match "FORCED SHUTDOWN" )
{
Write-host "Forced shutdown in Last Line"
Exit
}
else
{
  #Cuts out the date field from the string
$logDateTime = ($x.split("(",3)[-1]).trimend(")")
  #Comapres the current time to the Log date Time
$TimeDiff = New-TimeSpan -end $logDateTime

#If Time difference is greater than 5 Minutes Send email.
if ($TimeDiff.minutes -lt -5)
{
$email_body ="The $ATMName on server $Server has not written to its log file since $logDateTime and requires investigation  
   The log file can be found here: $logfile 
   This will trigger a Proclaim_emailalert." 
   send-mailmessage -to $to -from $from -subject $Subject -smtpserver "mail.internal.local" -body $email_body -bodyashtml;
}
}


I’d like to advocate the use of named regex groups to make sense of text files and logs. They make everything look so pretty.

Edit: Okay I tried pasting an example, but the website simply does not allow .NET style regex naming groups. It eats the triangle brackets.

Some Powershell functionality you should look into is here strings and splatting. Also, keep in mind you don’t need to use “Exit” because your if code block doesn’t do anything else if you meet the if criteria. Using Write-Host is also a bad practice. You can either just return a string or use [cmdletbinding()] and then you can use Write-Verbose to display information for trouble shooting using the -Verbose switch. Take a look at the below:

$Logfile ="C:\karl\ATM-E-DocsReceiptsproatm.log"
$Server ="Proclaim-ATM2"
$ATMName ="Edocs Reciepts ATM"

#check out Powershell splatting.  We define all parameters in
#a hash table and then can pass those to Send-MailMessage
$splat = @{to = "Karl@helphire.co.uk";
           from = "ATMMonitor@helphire.co.uk"
           subject = "Critical Message from node: $server";
           smtpserver = "mail.internal.local"
           attachments=$Logfile
           bodyashtml =$true
           }


$content = get-content $Logfile -tail 1
#Cuts out the date field from the string
$logDateTime = ($content.split("(",3)[-1]).trimend(")")

#Check out Powershell here strings.  Allows you to format
#something like HTML and pass it later.  Comes in handy
#with SQL queries as well.
$hereString =@" 

    
        An email message from our sponsor
    
    
        
            The $ATMName on server $Server has not written to its log file since $logDateTime and requires investigation
            The log file is attached for review.
            This will trigger a Proclaim_emailalert."
        
    

"@

#Dynamically add body parameter since body is ready
$splat.Add("body", $hereString)

#If last line contains specific words exit the script
if ( $content -match "FORCED SHUTDOWN" ) {
    "Forced shutdown in Last Line"
}
else {
    #Compares the current time to the Log date Time
    #If Time difference is greater than 5 Minutes Send email.
    if ((New-TimeSpan -end $logDateTime).minutes -lt -5) {
       Send-MailMessage @splat
    }
}

Great info rob & Martin. Can see the value in both of the alternatives.

Thanks for taking your time to help me out.