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
633 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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Need to create an object factory 2 47
Best method to remove 360 Safety Guard from Windows 8 4 395
URL to download Windows 10 Home 7 134
robocopy vs xcopy vs copy 8 130
Log files are useful in diagnosing and repairing problems.  This is a list of common log files and their standard locations that I've compiled.   While this is not exhaustive, it is a pretty good list that I've found to be useful.  I may update it f…
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
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…
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…

790 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