5
\$\begingroup\$

This is a namespace to read a bunch of events from a log file and display them in a table on a webpage, some additional data (computer domain and IP address) is also pulled in from DNS. I am mostly interested in the DNS parts as they are the modifications I made to someone else's code to change the source from an exported DHCP database to execution-time DNS lookups.

The final version below is much faster than the original and my intermediate attempts; there's no delay to get the DHCP database, DNS queries run in parallel and any that run longer than a second time out. Page load time is down to under 10 seconds from over a minute.

The parallel processing can cause a race condition if more than one DNS domain has a record with the same name. This is intended behaviour - the page is used by internal IT staff and I want them calling through strange stuff like duplicate DNS entries.

The GetDNS function is almost verbatim from here.

Design wise this is probably pretty terrible - I've only been working with code in any semi-serious way for a month (it's still not my main job), and I've never even touched C# before making this so please be brutal...it's the only way I'll learn.

I'm mostly interested in feedback on the style, syntax, any obvious newbie mistakes, and while the performance is much better it's probably got a way to go until 'good' so advice on that would be great too.

I'm especially interested in feedback on the parallelism such as it is; before I found the nice DNS timeout method some of my previous attempts had things like aborting threads and cancelling tasks, which compiled but caused all kinds of entertaining runtime errors.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.Security;
using System.Globalization;
using System.Threading;
using System.Data;
using System.Net;
using System.Configuration;
using System.Threading.Tasks;

namespace imtoolkit.Model
{

public class DNSHandler
{

    private delegate IPAddress[] DNSGetHandler(string ip);

    public string GetDNS(string ip, int timeout)
    {
        try
        {
            DNSGetHandler callback = new DNSGetHandler(Dns.GetHostAddresses);
            IAsyncResult result = callback.BeginInvoke(ip, null, null);
            if (result.AsyncWaitHandle.WaitOne(timeout, false))
            {
                IPAddress[] foo = callback.EndInvoke(result);
                string locAddy = "";
                bool togglejunk = false;
                bool lastIterationJunk = false;
                for (int index = 0; index < foo.Length; index++)
                {
                    lastIterationJunk = false;
                    if (togglejunk) { lastIterationJunk = true; }
                    if (index > 0 && lastIterationJunk == false) { locAddy = locAddy + " + "; }
                    string comparator = foo[index].ToString();
                    if (comparator == "::1") { togglejunk = true; continue; }
                    togglejunk = false;
                    locAddy = locAddy + foo[index];
                }
                return locAddy;
            }
            else
            {
                return ip;
            }
        }
        catch (Exception)
        {
            return ip;
        }
    }

}

public class LogReader
{

    private string queryString;

    public LogReader()
    {
        queryString = "";
    }

    public string QueryEvents(string trUserName, double timeWindow, ref DataTable eventDetails)
    {
        EventLogReader logReader;
        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

        //time string must be in the format 2014-10-20T08:54:26.982875000Z (micro seconds must be 9d+Z)
        // and System/TimeCreated/@SystemTime > '" + timestr + "' 
        // and [EventData[Data[@Name='SubjectLogonID']='" + trUserName + "']]
        string timestr = DateTime.Now.AddHours(-timeWindow).ToUniversalTime().ToString("o");
        timestr = timestr.TrimEnd('Z');
        int milLength = timestr.Length - (timestr.IndexOf(".") + 1);
        int nummstr = 9 - milLength;
        for (int nc = 0; nc < nummstr; nc++)
        {
            timestr = timestr + "0";
        }
        timestr = timestr + "Z";
        queryString = "*[System[(EventID='4740')]] and *[System[TimeCreated[@SystemTime > '" + timestr + "']]] and *[EventData[Data[@Name='TargetUserName'] and (Data='" + trUserName + "')]]";

        string logPath = System.Configuration.ConfigurationManager.AppSettings["logFilePath"];

        EventLogQuery query = new EventLogQuery(logPath, PathType.FilePath, queryString);

        int rowcount = 0;
        try
        {
            logReader = new EventLogReader(query);
            for (EventRecord eventInstance = logReader.ReadEvent(); null != eventInstance; eventInstance = logReader.ReadEvent())
            {
                //if (eventInstance.FormatDescription().Contains(trUserName))
                //if (eventInstance.FormatDescription().IndexOf(trUserName, StringComparison.OrdinalIgnoreCase) >= 0 )

                eventDetails.Rows.Add();
                if (eventDetails.Rows.Count > 0)
                {
                    eventDetails.Rows[rowcount]["UserID"] = trUserName;
                    eventDetails.Rows[rowcount]["LockoutTime"] = eventInstance.TimeCreated;
                    String eveDesc = eventInstance.FormatDescription().ToString();
                    String ccomputer = eveDesc.Substring((eveDesc.IndexOf("Caller Computer Name:") + 21));
                    ccomputer = ccomputer.Replace("\t", "");
                    String comSuffix = "";
                    string domainSuffixesRaw = System.Configuration.ConfigurationManager.AppSettings["lookupDomainSuffixes"];
                    string[] stringSeparators = new string[] { ",\r\n" };
                    string IPAddy = "";
                    string[] domainSuffixes = domainSuffixesRaw.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries);
                    Parallel.ForEach(domainSuffixes, (suffix) =>
                    {
                        try
                        {
                            DNSHandler DNH = new DNSHandler();
                            string foo = DNH.GetDNS(ccomputer + suffix, 1000);
                            if (foo != (ccomputer + suffix))
                            {
                            IPAddy = foo;
                            comSuffix = suffix;
                            }
                        }
                        catch (Exception) { }
                    });
                    if (IPAddy == "") { eventDetails.Rows[rowcount]["Computer"] = ccomputer; IPAddy = "DNS lookup failed"; eventDetails.Rows[rowcount]["IPAddress"] = IPAddy; }
                    else { eventDetails.Rows[rowcount]["Computer"] = ccomputer + comSuffix; eventDetails.Rows[rowcount]["IPAddress"] = IPAddy; }
                    eventDetails.Rows[rowcount]["EventDetails"] = eventInstance.FormatDescription().ToString();
                    rowcount++;
                }


            }
            string retgo = "";
            return retgo;
        }
        catch (EventLogException e)
        {
            string retever = (string.Format("Could not query the remote computer! {0}", e.Message));
            return retever;
        }

    }

}
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.