Solved

How can I write a Windows Powershell script to search the Windows event logs for occurrences of a certain string?

Posted on 2008-06-11
8
623 Views
Last Modified: 2012-08-14
Hi all,

I'm currently converting some old VB scripts to Windows Powershell.  The one I'm working on now looks at the event logs for a remote computer and searches the logs for all occurrences of a certain string then grabs information from the events when it finds a match.  My script's syntax looks ok but I keep getting an error saying "Quota violation" when I run the script.  Here's the script I'm using.  Can someone take a look at it and see if it looks ok?  The script is intended to be used to give back information regarding the time people connected to our Cisco VPN.  The server being searched is the IAS server for the Cisco VPN hence why I'm searching the Windows event logs for this stuff.

I'm totally open to the script being completely hacked to pieces if I'm doing this wrong.  The end result is that I want to look in the application log for a remote server for occurrences of a certain string then grab information from the events when a match is found (yes I know I'm repeating myself!).  The current script searches ALL the event logs - can it be restricted to the application log only?

*** script start ***

$strComputer = "server01.mydomain.local"

$colItems = get-wmiobject -class "Win32_NTLogEvent" -namespace "root\CIMV2" -computername $strComputer -credential "mydomain.local\myaccount"

foreach ($objItem in $colItems)
{
      if ($objItem.LogFile = "System")
      {
            if ($objItem.Message -ne $null)
            {
                  if ($objItem.Message.Contains("cisco_router_name"))
                  {
                        $userLocationStart = $objItem.Message.IndexOf("User") + 5
                        $userLocationFinish = $objItem.Message.IndexOf("was granted") - 1
                        $userStr = $objItem.Message.SubString($userLocationStart, $userLocationFinish - $userLocationStart)
                        $strVPNAccess = "$strVPNAccess $userStr - objItem.TimeWritten`r`n"
                  }
            }
      }            
}

*** script end ***

Thanks in advance!
0
Comment
Question by:Number5ix
  • 5
  • 3
8 Comments
 
LVL 18

Expert Comment

by:BSonPosh
ID: 21770014
I can definately tweak your code, but I think the "Quota violation" is entirely different issue. Your code is a tad bloated, but it looks functional.

Some thoughts:
1) Use Get-Credential and store it in a variable to pass to Get-WMIOBject
$creds = Get-Credential
2) $objItem.LogFile = "System" : "=" is an assignment operator not a comparison. Use "-eq"
($objItem.LogFile -eq "System")
3) This "if ($objItem.Message -ne $null)" can be changed to "if ($objItem.Message)"
4) The biggest benefit to Powershell is the pipeline... live it, love it, use it.

I will post some more in a moment
0
 
LVL 18

Accepted Solution

by:
BSonPosh earned 500 total points
ID: 21770307
Try this.. it should be quiet a bit faster.


$strComputer = "server01.mydomain.local"

$creds = Get-Credential

$strVPNAccess = @()
 

# Use a WMI filter to allow the Server to reduce the data sent back. Only return entries with Message you want

$Log = Get-WMIObject "Win32_NTLogEvent" -computername $strComputer -filter "LogFile='System'" -cred $creds | ?{$_.Message -match "cisco_router_name"}
 

foreach ($entry in $Log)

{

    $userLocationStart = $objItem.Message.IndexOf("User") + 5

    $userLocationFinish = $objItem.Message.IndexOf("was granted") - 1

    $userStr = $objItem.Message.SubString($userLocationStart, $userLocationFinish - $userLocationStart)

    $strVPNAccess += "{0} - {1}" -f $userStr,$entry.TimeWritten

}

Open in new window

0
 
LVL 18

Expert Comment

by:BSonPosh
ID: 21770329
- Notice the use of the WMI Filter: This reduces what the Server sends back instead of client side parsing.
- Notice the use of the pipe to filter out the Type of messages we want.
0
 
LVL 3

Author Comment

by:Number5ix
ID: 21777121
Great reply, thanks.  I'll have to wait until Monday before I can try it though so I'll update the question then.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 18

Expert Comment

by:BSonPosh
ID: 21779095
cool.. also if you post the "string" your parsing. Perhaps I can help with that.
0
 
LVL 3

Author Comment

by:Number5ix
ID: 21790397
Hi there BSonPosh,

I've had a hack at your answers above and, with a couple of modifications, it works beautifully, e.g. foreach ($entry in $Log) should be foreach ($objItem in $Log) because $objItem is referred to later, not $entry.  I also couldn't find a way of converting $objItem.TimeWritten to a nice human-readable format - that's why I ended up using all the SubString stuff below - is there a way of doing this quickly that you're aware of?  I've done heaps of .NET development outside of PS so feel free to throw in .NET stuff if you want.

However, the complete script as it stands now, with internal server names changed, is:

$strComputer = "myserver.mydomain.local"
$creds = Get-Credential
$strVPNAccess = @()
 
# Use a WMI filter to allow the Server to reduce the data sent back. Only return entries with Message you want
$Log = Get-WMIObject "Win32_NTLogEvent" -computername $strComputer -filter "LogFile='System'" -cred $creds | ?{$_.Message -match "cisco_router_name"}
 
foreach ($objItem in $Log)
{
      if ($objItem.Message)
      {
            $userLocationStart = $objItem.Message.IndexOf("User") + 5
            $userLocationFinish = $objItem.Message.IndexOf("was granted") - 1
            if ($userLocationFinish -ge 5)
            {
            
                  $timeWritten = $objItem.TimeWritten.SubString(6,2) + "/" `
                  + $objItem.TimeWritten.SubString(4,2) + "/" `
                  + $objItem.TimeWritten.SubString(0,4) + " " `
                  + $objItem.TimeWritten.SubString(8,2) + ":" `
                  + $objItem.TimeWritten.SubString(10,2) + ":" `
                  + $objItem.TimeWritten.SubString(12,2)
            
                  $userStr = $objItem.Message.SubString($userLocationStart, $userLocationFinish - $userLocationStart)
                  $userStr = $userStr.Trim()
                  $strVPNAccess += "<p class='content'>{0} - {1}</p>`r`n" -f $userStr,$timeWritten
                  
            }
    }
}

$strVPNAccessEmail += "<html>`r`n`r`n<head>`r`n<style type='text/css'>.title { font-family: 'Verdana'; font-size: 14px; } .content { font-family: 'Verdana'; font-size: 11px; }</style>`r`n</head>`r`n`r`n<body><p class='title'>VPN Access Summary</p>`r`n" + $strVPNAccess + "</body>`r`n`r`n</html>"

$mailer = new-object Net.Mail.SMTPclient("smtp.mydomain.local")
$mailer.port = 25
$msg = new-object Net.Mail.MailMessage("me@me.com","me@me.com","VPN Access Summary",$strVPNAccessEmail)
$msg.IsBodyHTML = $true
$mailer.send($msg)

THANKS!  :)
0
 
LVL 18

Expert Comment

by:BSonPosh
ID: 21793779
The $entry thing was intential.. I am trying to get you away from vbscript syntaxed Powershell :)

For the time string... I am not sure this is easier, but it definately more useful

This will return a datetime object instead
[System.DateTime]::ParseExact($objItem.TimeWritten,Split(".")[0],"yyyyMMddHHmmss",$null)
0
 
LVL 3

Author Comment

by:Number5ix
ID: 21797936
LOL yes I can see your point now re the $entry thing being intentional!  Thank you very much for your help though, it solved my PowerShell problem and is worth the 500 points & A grade rating.  :)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

INTRODUCTION The purpose of this document is to demonstrate the Installation and configuration of the Data Protection Manager product. Note that this demonstration was prepared on the basis of Windows OS is 2008 R2 and DPM 2010. DATA PROTECTI…
When you upgrade from Windows 8 to 8.1 or to Windows 10 or if you are like me you are on the Insider Program you may find yourself with many 450MB recovery partitions.  With a traditional disk that may not be a problem but with relatively smaller SS…
This video Micro Tutorial explains how to clone a hard drive using a commercial software product for Windows systems called Casper from Future Systems Solutions (FSS). Cloning makes an exact, complete copy of one hard disk drive (HDD) onto another d…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

895 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now