IIS7 Logparser Gadget

Bill sent me e-mail on Saturday announcing that he wrote his first Windows Sidebar Gadget. It allows him to start PerfMon or other arbitrary programs from the Windows Sidebar.

Logparser Gadget I wanted to write a gadget for a long time and use it for one or the other IIS7 demo in the three talks I give on TechEd Barcelona. Bill's mail made me finally do it. So I spent the whole day Saturday to come up with my own gadget and right before dinner time the "IIS7 Logparser Gadget" was born (click the link to download it).

It runs a user-definable Logparser query, reads the first result and shows it on the gadget. Here is how it works:

1) gadget.xml is a global configuration file containing descriptions, etc. Not too interesting. The only important entry is the html file that gets invoked to show the gadget. In our case it is Logparser.html.

<?xml version="1.0" encoding="utf-8" ?>
<gadget>
  <name>Logparser Gadget</name>
  <namespace>Logparser.Gadget</namespace>
  <version>1.0</version>
  <author name="Thomas Deml">
    <info url="www.iis.net" />
  </author>
  <icons>
    <icon src="icon.png" />
  </icons>
  <copyright>2006</copyright>
  <description>Logparser Gadget that runs custom query</description>
  <hosts>
    <host name="sidebar">
      <base type="HTML" apiVersion="1.0.0" src="Logparser.html" />
      <permissions>full</permissions>
      <platform minPlatformVersion="0.3" />
    </host>
  </hosts>
</gadget>

2) logparser.htm is the html file that contains the code that shows the gadget and runs the query. In logparser.html you find the meat of the gadget. The Javascript code defines the default logparser query (it looks a bit cryptic, but the query returns the sum of http requests that ran in the last hour) and sets up a timer to run the query every 30 seconds. If an error occurs I write it to the logparser_gadget_error.log file.

<html>
 <head>
  <title>Logparser Gadget</title>
  <style>
    body {
    width:130;
    height:74;
    background: url('Image.png');
    padding-top: 0px;
    }
  </style>
 </head>
 <body onload="countdown()" >
  <span id="gadgetContent" style='font-family: Calibri; font-size: 10pt; color: Black'>init</span>
  <script>
  <!--
    var g_logFileLocation = System.Environment.getEnvironmentVariable("systemdrive") + "\\inetpub\\logs\\logfiles\\w3svc1\\*.log"
    var g_queryInterval = 30000;
    var g_queryDescription = "Requests in the last hour: "
    var g_query = "SELECT COUNT(*) FROM " + g_logFileLocation + " WHERE SUB(TO_INT(TO_LOCALTIME(SYSTEM_TIMESTAMP())),TO_INT(TO_LOCALTIME(TO_TIMESTAMP(date,time)))) < 3600"
    System.Gadget.Settings.write("queryInterval", g_queryInterval);
    System.Gadget.Settings.write("queryDescription", g_queryDescription);
    System.Gadget.Settings.write("query", g_query);
    System.Gadget.settingsUI = "Settings.html"
    System.Gadget.onSettingsClosed = SettingsClosed;
    function SettingsClosed()
    {
      g_query = System.Gadget.Settings.read("query");
      g_queryInterval = System.Gadget.Settings.read("queryInterval");
      g_queryDescription = System.Gadget.Settings.read("queryDescription");
    } 
    function countdown()
    {
      var LogParser=new ActiveXObject("MSUtil.LogQuery");
      var recordSet;
      var result;
      var objInputFormat = new ActiveXObject("MSUtil.LogQuery.IISW3CInputFormat");
      objInputFormat.Recurse = 0;
      try {
        recordSet = LogParser.Execute( g_query, objInputFormat);
        for(; !recordSet.atEnd(); recordSet.moveNext())
        { 
          result = recordSet.getRecord().toNativeString(0);
        }
      }
      catch (err)
      {
        try {
          var fs = new ActiveXObject("Scripting.FileSystemObject");
          var logfilename = System.Environment.getEnvironmentVariable("temp") + "\\logparser_gadget_error.log"
          var logfile = fs.OpenTextFile(logfilename, 2, true);
          logfile.WriteLine(System.Time.getLocalTime(System.Time.currentTimeZone) + ": " + err.description);
          logfile.Close();
          gadgetContent.innerHTML = "Error - see logfile"
       }
       catch (errinner)
       {
         gadgetContent.innerHTML = errinner.description;
         return; 
       }
     }
     if (result != null)
     {
       gadgetContent.innerHTML = "<center>" + g_queryDescription + "<br><B>" + result + "</B></center>"
     }
     else
     {
       gadgetContent.innerHTML = "no results"
     }
       Id = window.setTimeout("countdown()",g_queryInterval);
     }
    -->
    </script>

  </body>
</html>

 

3) settings.htm is pretty straightfoward, too. It allows you to change the Logparser query, the query description and the query interval (defaults to run every 30 seconds right now). It gets called when you right click on the gadget and click "Options".

Logparser Gadget Options 

<html>
  <head>
   <style>
    body{
      width:600;
      height:200;
    }
   </style>
   <script>  

    System.Gadget.onSettingsClosing = SettingsClosing;
    function init() {
      query.value = System.Gadget.Settings.read("query");
      queryDescription.value = System.Gadget.Settings.read("queryDescription");
      queryInterval.value = System.Gadget.Settings.read("queryInterval");
    }

    function SettingsClosing(event)
    {
      if (event.closeAction == event.Action.commit) {
        System.Gadget.Settings.write("query", query.value);
        System.Gadget.Settings.write("queryDescription", queryDescription.value);
        System.Gadget.Settings.write("queryInterval", queryInterval.value);
      }
      event.cancel = false;
    }
   </script>
 </head>
 <body onload="init()">
   <div id="mySpan" style='font-family: Tahoma; font-size: 8pt; ' >
     Logparser Query:<br />
     <input style='font-family: Tahoma; font-size: 8pt; width: 250; ' type='text' id='query' ><br />
     Query Description:<br />
     <input style='font-family: Tahoma; font-size: 8pt; width: 250; ' type='text' id='queryDescription' length='600'><br />
     Refresh Interval (msec):<br />
     <input style='font-family: Tahoma; font-size: 8pt; ' type='text' id='queryInterval' length='10'>
   </div>
 </body>
</html>

4) image.png and icon.png are the backgrounds for the gadget referenced in gadget.xml and logparser.html.

How to install it?

Download and install Logparser 2.2. Create a gadget directory and copy the extracted files into it: md "%userprofile%\AppData\local\microsoft\Windows Sidebar\gadgets\logparser.gadget". Now right click on the Sidebar and select the Logparser Gadget:

Logparser Gadget Selection

Issues:

UAC bites again. If you run with User Account Protection on you don't have access to the IIS logfiles because they are ACLed to only allow Administrators. The only way around it right now is to ACL the logfiles to access for the identity Sidebar is running under. I usually do it like this:

ICACLS %systemdrive%\inetpub\logs\logfiles /grant %USERDOMAIN%\%USERNAME%:(CI)(OI)F /T

I hope this gives you an idea how to write your own gadgets. Have fun!

 

1 Comment

Comments have been disabled for this content.