?
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
Medium Priority
?
642 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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 2000 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
Get real performance insights from real users

Key features:
- Total Pages Views and Load times
- Top Pages Viewed and Load Times
- Real Time Site Page Build Performance
- Users’ Browser and Platform Performance
- Geographic User Breakdown
- And more

 
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
 
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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

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

This article describes how to set permissions to allow a limited-permissions user to start and stop a particular System Service.   It is always best to give users only the permissions that they need to perform their job, so tweaking particular permi…
The way I use Experts Exchange to assist me in analyzing and diagnosing a problem is I first enter a Verbose Question at Experts Exchange like: Office 2007 will hang when opening and saving files I then launch WordPad (any text editor will do) an…
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…
With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…

762 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