Contents tagged with Programming

  • Using the FileSystemWatcher to watch a folder for changes usually turns out to be a bad idea. From missing notifications to IOExceptions when trying to copy files, I’ve just given up on using FileSystemWatcher to do anything useful. I find that using Quartz.NET to set up a simple scheduled task that polls the folder occasionally is a more reliable and robust solution. Just remember to use stateful jobs to ensure your tasks don’t overlap.

  • Logging is a critical piece of infrastructure for any application. On most of my projects, I use log4net because it’s a tried and tested framework that does exactly what it says on the box and stays out of your way. Today, I wanted to start logging security events in an application I’m building. By security events, I mean things like users logging in and out, changing passwords, and so on.

    I’m currently using text files to hold all my logs because I think logging infrastructure should be as simple as possible. For all the benefits of using a database to hold logs, I think it adds too many points where things could go wrong, potentially resulting in lost or missing log data. Now, when you’re keeping your logs in plain-text, you need to be careful to structure the log output so you can parse the data easily. The most straightforward way to do this without having to pepper your log data itself with magic strings is to use appropriate log levels.

    Out of the box, log4net provides five different log levels:

    1. Debug
    2. Error
    3. Fatal
    4. Info
    5. Warn

    I wanted to add things like “Login” and “Logout” to this list. It turns out that this is relatively straightforward to accomplish with log4net.

    The first thing you need to do is to create and register your new levels with the LogManager like this:

    log4net.Core.Level authLevel = new log4net.Core.Level(50000, "Auth");
    log4net.LogManager.GetRepository().LevelMap.Add(authLevel);
    

    It’s important that you do this before configuring log4net.

    Adding some extension methods makes it dead simple to start using the new log levels:

    public static class SecurityExtensions
    {
        static readonly log4net.Core.Level authLevel = new log4net.Core.Level(50000, "Auth");
    
        public static void Auth(this ILog log, string message)
        {
            log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, 
                authLevel, message, null);
        }
    
        public static void AuthFormat(this ILog log, string message, params object[] args)
        {
            string formattedMessage = string.Format(message, args);
            log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType,
                authLevel, formattedMessage, null);
        }
    
    }

    And that’s it – now I can start using my new “Auth” logging level on any instance of ILog like this:

    SecurityLogger.AuthFormat("User logged in with id {0} from IP address {1}", id, Request.UserHostAddress);
  • Recently I came across a requirement to create an ATL ActiveX control that could be used from JavaScript in the following manner:

    o = new ActiveXObject("Test.MyControl");
    o.OnStateChanged = MyEventHandler;
    

    I figured this would be pretty simple -- just implement an ActiveX control with connection points. Unfortunately, it doesn't work. Internet Explorer complains thus:

    ie7_object_error 

    This is because JavaScript can't sink COM events. This seemed odd to me, because the same approach works when you try to use the XMLHttpRequest object. As it turns out, XMLHttpRequest doesn't implement "events" as COM events at all. They're actually properties that accept IDispatch pointers. JavaScript functions are marshalled to ActiveX as objects that implement IDispatch and having a method named "call".

    Simply put, this is what we need to do to enable ActiveX events to be handled by JavaScript using the syntax shown above:

    1) Implement a property in the ActiveX control that accepts an IDispatch pointer.

    STDMETHODIMP CTestCtrl::putref_OnStateChanged(IDispatch* newVal)
    STDMETHODIMP CTestCtrl::get_OnStateChanged(IDispatch** pVal)
    

    2) Get the DISPID of the "call" method by calling GetIDsOfNames like so:

    newVal->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, pDispId))

    3) When you want to invoke the event, construct a VARIANTARG containing the parameters you want to pass to the event in reverse order. Add a pointer to your own IDispatch implementation as the last element in the array.

    DISPPARAMS dispParams;
    VARIANTARG args[2];
    
    VariantInit(&args[0]);
    args[0].vt = VT_BSTR;
    args[0].bstrVal = ::SysAllocString(L"The event says hello!");
    
    IDispatch* pDisp;
    HRESULT hRes = this->QueryInterface(IID_IDispatch, (void**)&pDisp);
    
    VariantInit(&args[1]);
    args[1].vt = VT_DISPATCH;
    args[1].pdispVal= pDisp;
    
    memset(&dispParams, 0, sizeof(dispParams));
    dispParams.rgvarg = args;
    dispParams.cArgs = sizeof(args)/sizeof(args[0]);
    
    EXCEPINFO excepinfo; 
    UINT uArgErr;
    
    pEventHandler->Invoke(*pDispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, 
        DISPATCH_METHOD, &dispParams, NULL, &excepinfo, &uArgErr);
    

    4) Clean up when you're done by calling VariantClear on both elements of the args array.

  • H.L. Mencken once said:

    There is always a well-known solution to every human problem--neat, plausible, and wrong.

    It's generally agreed in the programming world that simple, easy to understand code is preferred over highly convoluted code even if it is at the expense of some efficiency.

    A few days ago, Jeff Attwood wrote about what seemed to be a trivial programming exercise -- shuffling a deck of cards. Jeff's first idea went something like this:

    for (int i = 0; i < cards.Length; i++)
    {
        int n = rand.Next(cards.Length);
        Swap(ref cards[i], ref cards[n]);
    }

    It is only a couple of lines of code. How hard can it be to get it right? If only it were that simple!

    Jeff explains in a later post how seriously flawed that shuffle algorithm is. The seemingly simple shuffle algorithm has a distinct bias. This becomes apparent only when it's tested over a very large number of runs.

    The right way to shuffle is the Knuth-Fisher-Yates algorithm:

    for (int i = cards.Length - 1; i > 0; i--)
    {
        int n = rand.Next(i + 1);
        Swap(ref cards[i], ref cards[n]);
    }
    

    The difference in the code is subtle, to say the least. But as Jeff explains quite beautifully, it makes a world of difference in the net result.

    This simple example explains excellently the need for two things:

    1. A well thought out testing strategy, and
    2. A deep understanding of the domain you're working in.

    Who would've thought shuffling a deck of cards would be so hard to get right?