Previous Section Table of Contents Next Section

The Result

The final script is a combination of the original static HTML, the functions I created, and the inline script code I created. Merging everything results in the working event log Web viewer.

graphics/arrow.gif Event Log Viewer

Listing 22.1 shows the final event log viewer, in its entirety.

Listing 22.1. Event.asp. Displays local and remote event logs in a Web browser.

<%



'Was the form submitted?

If Request.Form("SUBMIT") = "" Then



 'No - set up the form

 'Start by getting the local computer name

 Set oNet =CreateObject("WScript.Network")

 sCompName=oNet.Computername

 Response.Write "Computer: " & compname & "<BR>"

 Set oNet = Nothing



 'Now display the HTML form

%>

<FORM ACTION="event.asp" METHOD="POST">

 <Table cellpadding=2 cellspacing=2 border=0>

  <TR>

   <TD>

    <INPUT type="text" name="ComputerName"

     value="<% Response.Write CompName%>">

   </TD>

   <TD>Computer:</TD>

  </TR>

  <TR>

   <TD>

    <SELECT name="LogName">

     <OPTION value="application">Application</OPTION>

     <OPTION value="system">System</OPTION>

     <OPTION value="security">Security</OPTION>

     </SELECT>

    </TD>

    <TD>Log</TD>

   </TR>

   <TR>

    <TD><INPUT type="text" name="Source"></TD>

    <TD>Event Source</TD>

   </TR>

   <TR>

    <TD>

     <SELECT name="Type">

      <OPTION value="">All</option>

      <OPTION value="information">Information</OPTION>

      <OPTION value="warning">Warning</OPTION>

      <OPTION value="error">Error</OPTION>

     </SELECT>

    </TD>

    <TD>Type</TD>

   </TR>

  <TR>

   <TD><input type="text" name="EventCode"></TD>

   <TD>Event Code</TD>

  </TR>

  <TR>

   <TD><input type="text" name="UserName"</TD>

   <TD>User Name</TD>

  </TR>

  <TR>

   <TD><input type="password" name="Password"></TD>

   <TD>Password</TD>

  </TR>

  <TR>

   <TD COLSPAN=2 Align=center>

    <INPUT type="submit" NAME="Submit" VALUE="Submit">

   </TD>

  </TR>

 </TABLE>

</FORM>



<%

'Here's the end of the original If...Then

'This is executed if the form was submitted

Else



 'declare variables

 Dim oServices, oResultset, oRecord

 Dim sComputerName, sLogFile, sQuery

 Dim dtDate, dtTime



 'get the network object

 set oNet =CreateObject("WScript.Network")



 'get a WMI locator

 set oLocator = CreateObject("WbemScripting.SWbemLocator")



 'get the local computer name

 sComputerName = oNet.ComputerName



 'build the WMI query

 sQuery = "SELECT * FROM Win32_NTLogEvent WHERE Logfile="



 'computer name specified?

 If(Request("ComputerName") <> "") Then

  sComputerName = Request("ComputerName")

 End If



 'log filename specified?

 If(Request("LogName")<> "") Then

  sLogFile = Request("LogName")

 End If



 'append computer name and log file

 'to WMI query

 sQuery = sQuery & """" & sLogFile & """"



 'add source, type, and code to query

 If(Request("Source")<> "") Then

  sQuery = sQuery & " AND SourceName=" & """" & _

   Request("Source") & """"

 End If

 If(Request("Type") <>"") Then

  sQuery = sQuery & " AND Type=" & """" & _

   Request("Type") & """"

 End If

 If(Request("EventCode") <>"") Then

  sQuery = sQuery & " AND EventCode=" & _

   """" & Request("EventCode") & """"

 End If



 'username is blank?

 If Request.form("UserName") <> "" Then

  'no - connect to local machine

  Set oServices = oLocator.ConnectServer(sComputerName, _

   "root\default", Request.form("UserName"), _

   Request.Form("Password"))



 Else

  'yes = connect to local computer

  Set oServices = oLocator.ConnectServer(sComputerName )

 End If



'execute query

 Set oResultset = oServices.ExecQuery(sQuery)



 'any results?

 If(oResultset.Count = 0) Then

  'no

  Response.Write "<b>Query returned 0 records.</b>"

 Else

  'yes - display results



  'build table header

  Response.Write "<TABLE cellspacing=0 cellpadding=3 border=1>"



  'build first table row

  Response.Write "<TR>"

  Response.Write "<TH>Record</TH>"

  Response.Write "<TH>Type</TH>"

  Response.Write "<TH>Date</TH>"

  Response.Write "<TH>Time</TH>"

  Response.Write "<TH>Source</TH>"

  Response.Write "<TH>Category</TH>"

  Response.Write "<TH>Cat Strg</TH>"

  Response.Write "<TH>Event</TH>"

  Response.Write "<TH>Usr</TH>"

  Response.Write "<TH>Computer</TH>"

  Response.Write "<TH>Msg</TH>"

  Response.Write "</TR>"



  'go through each event entry

  For Each oRecord In oResultset

   'Format the date and time of the entry

   dtDate = CDateWMI(oRecord.TimeGenerated)

   dtTime = CTimeWMI(oRecord.TimeGenerated)





   'write row tag

   Response.Write "<TR>"



   'write cell tag & record information

   Response.Write "<TD>" & oRecord.RecordNumber &" </TD>" & _

   "<TD>" & oRecord.Type & "</TD>" & _

   "<TD>" & dtDate & "</TD>" & _

   "<TD>" & dtTime & "</TD>" & _

   "<TD>" & oRecord.SourceName & "</TD>" & _

   "<TD>" & oRecord.Category & "</TD>" & _

   "<TD>" & oRecord.CategoryString & "</TD>" & _

   "<TD>" & oRecord.EventCode & "</TD>" & _

   "<TD>" & oRecord.User & "</TD>" & _

   "<TD>" & oRecord.ComputerName & "</TD>" & _

   "<TD>" & oRecord.Message & "</TD></TR>"



  Next



   'close the table

   Response.Write "</TABLE> </FONT>"



 End If



'custom functions

Function CDateWMI(cim_DateTime)

 'declare variables

 Dim sDateTime, iYear, iMonth, iDay



 'convert the date to a string

 sDateTime = CStr(cim_DateTime)



 'get the year, month, and day

 iYear = CInt(Mid(sDateTime, 1, 4))

 iMonth = CInt(Mid(sDateTime, 5, 2))

 iDay = CInt(Mid(sDateTime, 7, 2))



 'reformat into a normal date

 CDateWMI = CDate(Join(Array(iMonth, iDay, iYear), "/"))

End Function



Function CTimeWMI(cim_DateTime)

 'declare variables

 Dim sDateTime, iHours, iMinutes, iSeconds



 'convert the time into a string

 sDateTime = CStr(cim_DateTime)



 'get the hours, minutes, and seconds

 iHours = CInt(Mid(sDateTime, 9, 2))

 iMinutes = CInt(Mid(sDateTime, 11, 2))

 iSeconds = CInt(Mid(sDateTime, 13, 2))



 'reformat into a normal time

 CTimeWMI = TimeSerial(iHours, iMinutes, iSeconds)

 End Function



End If

%>

You shouldn't have to make any changes to this code to get it running in your environment. Just make sure you're using the appropriate user credentials.

NOTE

This script transmits passwords in clear text from your Web browser to the Web server. I don't advise using this script outside of a lab environment unless you secure the connection with a VPN or by using SSL encryption on the Web server. Because you'll be providing administrative passwords, anyone with a network sniffer could intercept the password and wreak havoc on your network.


graphics/arrow.gif Event Log Viewer-Explained

The script starts out by seeing whether the form was submitted.


<%



'Was the form submitted?

If Request.Form("SUBMIT") = "" Then

If the form wasn't submitted, I first retrieve the local computer name. This allows me to display that as a default selection. To get the name, I use the WScript.Network object.


'No - set up the form

'Start by getting the local computer name

Set oNet =CreateObject("WScript.Network")

sCompName=oNet.Computername

Response.Write "Computer: " & compname & "<BR>"

Set oNet = Nothing

The script continues by displaying the main HTML form. Notice that I've inserted the local computer name as the default value for the "ComputerName" text box. I've highlighted that code in boldface. I often make little tweaks like this to my static HTML just to make a page a bit easier to use, if I can.


 'Now display the HTML form

%>

<FORM ACTION="event.asp" METHOD="POST">

 <Table cellpadding=2 cellspacing=2 border=0>

  <TR>

   <TD>

    <INPUT type="text" name="ComputerName"

     value="<% Response.Write CompName%>">

   </TD>

   <TD>Computer:</TD>

  </TR>

  <TR>

   <TD>

    <SELECT name="LogName">

     <OPTION value="application">Application</OPTION>

     <OPTION value="system">System</OPTION>

     <OPTION value="security">Security</OPTION>

     </SELECT>

    </TD>

    <TD>Log</TD>

   </TR>

   <TR>

    <TD><INPUT type="text" name="Source"></TD>

    <TD>Event Source</TD>

   </TR>

   <TR>

    <TD>

     <SELECT name="Type">

      <OPTION value="">All</option>

      <OPTION value="information">Information</OPTION>

      <OPTION value="warning">Warning</OPTION>

      <OPTION value="error">Error</OPTION>

     </SELECT>

    </TD>

    <TD>Type</TD>

   </TR>

  <TR>

   <TD><input type="text" name="EventCode"></TD>

   <TD>Event Code</TD>

  </TR>

  <TR>

   <TD><input type="text" name="UserName"</TD>

   <TD>User Name</TD>

  </TR>

  <TR>

   <TD><input type="password" name="Password"></TD>

   <TD>Password</TD>

  </TR>

  <TR>

   <TD COLSPAN=2 Align=center>

    <INPUT type="submit" NAME="Submit" VALUE="Submit">

   </TD>

  </TR>

 </TABLE>

</FORM>



<%

'Here's the end of the original If...Then

'This is executed if the form was submitted

Else

This is the end of the static HTML. If the form wasn't submitted, this is the last thing the script executes. On the other hand, if the form was submitted, everything after Else is the first thing that is executed.

I start by declaring a handful of variables that I'll use later.


'declare variables

Dim oServices, oResultset, oRecord

Dim sComputerName, sLogFile, sQuery

Dim dtDate, dtTime

Next, I get a reference to the WScript.Network object. Didn't I already do this? Yes, but in the section of code that is called when the form wasn't submitted. That code hasn't executed this time around, because the form was submitted. Therefore, I need to get the object reference.


'get the network object

set oNet =CreateObject("WScript.Network")

I also need to get a WMI locator so that I can find whatever computer I plan to connect to.


 'get a WMI locator

set oLocator = CreateObject("WbemScripting.SWbemLocator")

Now I can use the WScript.Network object to retrieve the local computer name.


 'get the local computer name

sComputerName = oNet.ComputerName

I've declared a string variable to store the WMI query; I'll populate that variable with the first part of the query. Notice how I leave the query hanging at the end; I'll append more information as the script runs.


 'build the WMI query

sQuery = "SELECT * FROM Win32_NTLogEvent WHERE Logfile="

If the user provides a computer name in the form, I want to pull that into a variable. Similarly, if the user specifies a log name, I want to pull that into a variable, too.


 'computer name specified?

If(Request("ComputerName") <> "") Then

 sComputerName = Request("ComputerName")

End If



'log filename specified?

If(Request("LogName")<> "") Then

 sLogFile = Request("LogName")

End If

Now I can add on to the WMI query by adding the log filename.


'append computer name and log file

'to WMI query

sQuery = sQuery & """" & sLogFile & """"

The user can optionally specify an event source, type, and event code to filter on. If any of those three are specified, I need to add the appropriate criteria to the query.


 'add source, type, and code to query

If(Request("Source")<> "") Then

 sQuery = sQuery & " AND SourceName=" & """" & _

  Request("Source") & """"

End If

If(Request("Type") <>"") Then

 sQuery = sQuery & " AND Type=" & """" & _

  Request("Type") & """"

End If

If(Request("EventCode") <>"") Then

 sQuery = sQuery & " AND EventCode=" & _

  """" & Request("EventCode") & """"

End If

Next, I need to see whether the user name was filled in. If it wasn't, I use the WMI locator to connect to the appropriate remote machine, providing the user name and password that the user typed. Otherwise, I force WMI to connect to the local computer, using the computer name I got from the WScript.Network object.


'username is blank?

If Request.form("UserName") <> "" Then

 'no - connect to machine

 Set oServices = oLocator.ConnectServer(sComputerName, _

  "root\default", Request.form("UserName"), _

  Request.Form("Password"))



Else

 'yes = connect to local computer

 Set oServices = oLocator.ConnectServer(sComputerName )

End If

Now I can execute the WMI query against the computer I connected to. This returns a WMI result set, hopefully consisting of one or more event log entries.


'execute query

Set oResultset = oServices.ExecQuery(sQuery)

I cannot safely assume that any entries came back. After all, the log might be empty, or perhaps no entries matched the criteria provided. So, I check to see if the result set is empty, and if it is, I display a message to that effect. If the result set isn't empty, the script continues to execute.


'any results?

If(oResultset.Count = 0) Then

 'no

 Response.Write "<b>Query returned 0 records.</b>"

Else

 'yes - display results

First, I have to write out the HTML table header. I already worked out this HTML code earlier; this is using Response.Write to produce the code into the stream of HTML being sent to the Web browser.


 'build table header

Response.Write "<TABLE cellspacing=0 cellpadding=3 border=1>"



'build first table row

Response.Write "<TR>"

Response.Write "<TH>Record</TH>"

Response.Write "<TH>Type</TH>"

Response.Write "<TH>Date</TH>"

Response.Write "<TH>Time</TH>"

Response.Write "<TH>Source</TH>"

Response.Write "<TH>Category</TH>"

Response.Write "<TH>Cat Strg</TH>"

Response.Write "<TH>Event</TH>"

Response.Write "<TH>Usr</TH>"

Response.Write "<TH>Computer</TH>"

Response.Write "<TH>Msg</TH>"

Response.Write "</TR>"

Next, I'll use a For Each…Next loop to go through each result in the result set. Each result represents a single record, or event log entry.


'go through each event entry

For Each oRecord In oResultset

Each entry has a TimeGenerated property that's a combination date and time. I already wrote functions to reformat this data into something more legible, so I'll call those functions now.


'Format the date and time of the entry

dtDate = CDateWMI(oRecord.TimeGenerated)

dtTime = CTimeWMI(oRecord.TimeGenerated)

Now I can write the HTML code for the data row. I'll just write out the appropriate <TD> and </TD> tags, along with the desired properties from the oRecord object, which is used to represent the current event log entry.


'write row tag

Response.Write "<TR>"



'write cell tag & record information

Response.Write "<TD>" & oRecord.RecordNumber &" </TD>" & _

"<TD>" & oRecord.Type & "</TD>" & _

"<TD>" & dtDate & "</TD>" & _

"<TD>" & dtTime & "</TD>" & _

"<TD>" & oRecord.SourceName & "</TD>" & _

"<TD>" & oRecord.Category & "</TD>" & _

"<TD>" & oRecord.CategoryString & "</TD>" & _

"<TD>" & oRecord.EventCode & "</TD>" & _

"<TD>" & oRecord.User & "</TD>" & _

"<TD>" & oRecord.ComputerName & "</TD>" & _

"<TD>" & oRecord.Message & "</TD></TR>"

That's almost it. I can close up the For Each loop, and after all records have been processed, write out the HTML tags that close the table.


Next



 'close the table

 Response.Write "</TABLE> </FONT>"



End If

Finally, I've thrown in the two custom functions I wrote. These were used earlier in the script. The first one simply starts by pulling the date and time data into a string variable. Then, it uses substring functions (Mid()) to pull out the year, month, and day. It ends by using string array functions to create a normal-looking date from the results.


'custom functions

Function CDateWMI(cim_DateTime)

 'declare variables

 Dim sDateTime, iYear, iMonth, iDay

 'convert the date to a string

 sDateTime = CStr(cim_DateTime)



 'get the year, month, and day

 iYear = CInt(Mid(sDateTime, 1, 4))

 iMonth = CInt(Mid(sDateTime, 5, 2))

 iDay = CInt(Mid(sDateTime, 7, 2))



 'reformat into a normal date

 CDateWMI = CDate(Join(Array(iMonth, iDay, iYear), "/"))

End Function

For more information on substrings, see "Working with Substrings" in Chapter 8. For more information on array handling, see "Working with Arrays" in Chapter 9.

The next function does substantially the same thing, only it pulls data from different locations to get the hours, minutes, and seconds portion of the event entry's creation date.


Function CTimeWMI(cim_DateTime)

 'declare variables

 Dim sDateTime, iHours, iMinutes, iSeconds



 'convert the time into a string

 sDateTime = CStr(cim_DateTime)



 'get the hours, minutes, and seconds

 iHours = CInt(Mid(sDateTime, 9, 2))

 iMinutes = CInt(Mid(sDateTime, 11, 2))

 iSeconds = CInt(Mid(sDateTime, 13, 2))



 'reformat into a normal time

 CTimeWMI = TimeSerial(iHours, iMinutes, iSeconds)

 End Function



End If

%>

That's it! One complete Web page script, ready to go.

    Previous Section Table of Contents Next Section