Saturday, March 03, 2007

Dumping events

I'm often surprised (or is it dismayed) when questions pop up in news groups surrounding things like event orders for winforms or webforms applications... this isn't rocket science... we're given all the tools to make this easy to figure out!

Lets do a winforms 2.0 app as an example... first off, the earliest point at which can easily get involved is the constructor...  lets have a look:

public partial class Form1 : Form

{

    public Form1()

    {

        AttachToAllEvents();

        InitializeComponent();           

    }


So I'm going to attach to all the events before the forms components are initialized... now lets have a look at the "AttachToAllEvents" method.

private void AttachToAllEvents()

{           

    Type type = GetType();                      

 

    foreach (EventInfo info in type.GetEvents())

    {

        string eventName = info.Name;

 

        EventHandlerWrapper wrapper = new EventHandlerWrapper(new EventHandler(

            delegate

            {

                Console.WriteLine("{0}: EventName: {1}, IsVisible: {2}, IsHandleCreated: {3}, HasChildren: {4}, IsDisposed: {5}",

                                       DateTime.Now, eventName, this.Visible, this.IsHandleCreated, this.HasChildren,

                                       this.IsDisposed);                                                                       

            }));

 

        wrapper.Attach(this, info);               

    }

}


Only magic there is we're using a class called "EventHandlerWrapper" - what's that... well, it's used to create a strongly typed delegate for attaching to an event.

The reason we need this at all is because EventInfo.AddEventHandler(...) is fussy about the kind of delegate you supply, so if you pass in an "EventHandler" for a "CancelEventHandler" event, it'll throw an exception complaining about it's inability to cast between them... there might be an easier way to do this, but I haven't come across it so far.

public class EventHandlerWrapper

{

    private EventHandler _handler;

    private static readonly MethodInfo _methodInfo;

 

    static EventHandlerWrapper()

    {

        _methodInfo = typeof(EventHandlerWrapper).GetMethod("InvokeHandler", BindingFlags.NonPublic | BindingFlags.Instance);

    }

 

    public EventHandlerWrapper(EventHandler handler)

    {

        if (handler == null) throw new ArgumentNullException("handler");

        _handler = handler;

    }

 

    public void Attach(object target, EventInfo info)

    {

        Delegate wrappedHandler = Delegate.CreateDelegate(info.EventHandlerType, this, _methodInfo);

        info.AddEventHandler(target, wrappedHandler);       

    }

 

    private void InvokeHandler(object sender, EventArgs args)

    {

        _handler(sender, args);

    }

}


With a little brain power I'm sure I could've done this without the separate wrapper class, but this is probably a little easier to read at any rate.

Results..?

So.. onto the results - once we run the code and see exactly what order events are happening in, we can then make a pretty table that may not render in most browsers because I cut 'n pasted it from Excel 2007 ;o)

EventName  IsVisible  IsHandleCreated  HasChildren  IsDisposed
Resize  False  False  False  False
SizeChanged  False  False  False  False
ClientSizeChanged  False  False  False  False
ClientSizeChanged  False  False  False  False
ControlAdded  False  False  True  False
ControlAdded  False  False  True  False
StyleChanged  False  False  True  False
TextChanged  False  False  True  False
Move  False  True  True  False
LocationChanged  False  True  True  False
HandleCreated  False  True  True  False
Invalidated  False  True  True  False
StyleChanged  False  True  True  False
ChangeUICues  True  True  True  False
Invalidated  True  True  True  False
BindingContextChanged  True  True  True  False
Load  True  True  True  False
Layout  True  True  True  False
VisibleChanged  True  True  True  False
Activated  True  True  True  False
Shown  True  True  True  False
Paint  True  True  True  False
Paint  True  True  True  False
Paint  True  True  True  False
MouseCaptureChanged  True  True  True  False
Closing  True  True  True  False
FormClosing  True  True  True  False
Closed  True  True  True  False
FormClosed  True  True  True  False
Deactivate  True  True  True  False
HandleDestroyed  True  True  True  False
Disposed  False  False  False  False

The main thing to keep in mind when doing something like this is to avoid making assumptions - we may not be the first or last to attach to the events (depending on the complexity of the form) - and events can trigger other events... which could explain the ordering of some of this data i.e. changes in visibility and handle creation... if anything we are viewing the order of consequences, as opposed to the true order in which the events are invoked (to get that we'd need to override all the OnXXXX methods of the form class... which would be a good job for dynamic proxy :)
posted @ Saturday, March 03, 2007 12:54:32 AM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |
 Thursday, March 01, 2007
I've been using tortoise SVN for a couple of years now... but I'd never seen this dialog before when renaming files with similar name patterns... probably old news to some people, but it pleased me no end, very helpful!




It's these kinds of features that I like about an explorer based SCM client... I find IDE integrated source control just bugs me now days (like Team System which I use for codeplex).
posted @ Wednesday, February 28, 2007 11:38:48 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |
 Wednesday, February 28, 2007
In the last post about WiX shortcuts I detailed how to make an unisntall link... it was actually slightly wrong ;o) ... well at least if your product Id wasn't surrounded with braces... so here's the offending line fixed for product Guid's that aren't surrounded with braces (which is generally what you should be using in a WiX file)

<CustomAction Id="SetUninstallArgs" Property="UNINSTALLARGS" Value="/x {$(var.PRODUCTGUID)}" />


As you were...

posted @ Wednesday, February 28, 2007 6:48:27 AM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |

(Long) Shortcuts

Shortcuts are a basic concept in installers... and doing them with WiX is easy... once you know how... I just spent the last 10 minutes trying to get an Icon assigned to an advertised shortcut, here's how you do it...

<Component Id="StandAloneApplication" Guid="C8D5DB05-2D68-40e8-88D1-EF5BEA18DBE1">

  <File Id="SomeCompanySomeProductHostApp"

        Name="SomeCompany.SomeProduct.HostApp.exe"

        DiskId="1"

        Source="..\..\build\SomeCompany.SomeProduct.HostApp.exe"

        Vital="yes">

 

    <Shortcut Advertise="yes"

              Id="SomeCompanySomeProductHostAppShortcut"

              Directory="ProgramMenuDir"

              Name="My Product"

              WorkingDirectory="INSTALLDIR"

              Description="SomeProduct Application"

              Icon="HostAppShortcutIcon.exe">

 

      <Icon Id="HostAppShortcutIcon.exe"

            SourceFile="..\..\build\SomeCompany.SomeProduct.HostApp.exe" />

 

    </Shortcut>

  </File>

</Component>


The oddity is the way the Icon must be named with an ".exe" extension for it to work....  For non-advertised shortcuts you can get away with just leaving the icon out altogether.

Now something else my client wanted that I had to wrestle with a bit... how to create an uninstall shortcut for your product in the program menu's directory... here's how I achieved it, by creating a shortcut to msiexec.exe - I'm damn sure there must be easier way though, this is very clunky, but at least it works for now - if anyone knows an easier way then drop me a comment...

Personally I think uninstall links in the program menu are a waste of time... but in this case I wasn't the target audience I guess :P

Note: The "$(var.PRODUCTGUID)" refers to a constant being passed to WiX from my continuous integration build (I have a custom msbuild task for generating a single unique productId guid per revision in SVN)...

First off I define a couple of custom actions...

<CustomAction Id="SetUninstallArgs" Property="UNINSTALLARGS" Value="/x $(var.PRODUCTGUID)" />

<CustomAction Id="SetUninstallCmd" Property="UNINSTALLCMD" Value="MSIEXEC.EXE" />

I then evaluate them as part of the "InstallExecuteSequence" ... this doesn't actually have to be run before "FindRelatedProducts"... you can evaluate them quite late in the installation process.

<InstallExecuteSequence>

  <Custom Action="SetUninstallArgs" Before="FindRelatedProducts" />

  <Custom Action="SetUninstallCmd" Before="FindRelatedProducts" />


And then we can create our shortcut...

<Component Id="Uninstaller" Guid="0454D0FC-190C-42c9-9506-DBA17DECBCB2"

  <RegistryKey Action="createAndRemoveOnUninstall" Root="HKCU" Key="Software\MyProduct\Uninstaller">

    <RegistryValue Value="" Type="string" KeyPath="yes" />

  </RegistryKey>

  <Shortcut Id="InvokeRemove" Name="Uninstall" Target="[UNINSTALLCMD]" Arguments="[UNINSTALLARGS]" WorkingDirectory="SystemDir" Directory="ProgramMenuDir" Description="Uninstall" />

</Component>


You might be wondering why I place a dummy registry entry in there... well it's because otherwise you end up with an ICE 38 error - which seems daft to me, but then I don't really know enough about the windows installer architecture to dispute ICE's errors ;o) (ICE stands for Internal Consistency Evaluator(s) - which is used to validate the installer produced by WiX - have a look here for more info).

At any rate... I like the way WiX works... I would never go back to a gui-based setup project tool again, they might be fine for small projects, but once your project grows it just starts to suck hard... why? well... 4 reasons off the top of my head:
  • You can't diff between versions easily... just what did you coworker change in the setup last checkin?
  • Lack of global search and replace...
  • Generally a little more difficult to fit into CI builds.
  • Some of the products require you to use regasm or CLR code to register assemblies for com interop.
I just wish there was a decent cookbook... WiX has been going for over 2 years now, and It still seems a little hard to find decent information, I mostly rely on the official stuff... and of course examining how some open source projects have build their installers.
I might post a little bit on upgrades next time, that's the other task that took me a little time to get sorted, might proove useful to someone starting out with WiX... who could say.

BTW - I haven't forgotten about my LINQ series... It's just on the back burner at the moment.
posted @ Wednesday, February 28, 2007 4:35:54 AM (New Zealand Daylight Time, UTC+13:00)    Comments [4] | Trackback |
 Friday, February 23, 2007

Changes in the wind...


I'm looking at expanding my operation (Dev Defined Limited) - after having come to the conclusion that I can't support my current client base, and certainly can't offer them enough business continuity should I be put out of action - short of taking key man insurance out on myself ;o) - I need to start growing.

At any rate I've decided to do a few things:
  1. Start engaging old clients (and finding new clients) to queue up more work beyond my capacity.
  2. Taking on additional staff to both do that work, and transfer knowledge about existing clients and solutions.
Which brings me to the point of this post, I'm going to be looking for a couple of additional development staff (both senior).

So if you're a flexible senior developer, with a strong .Net background who wants to help build a development shop up, and is looking for opportunities to stretch their legs and play with some new and interesting technologies (instead of just reading about them on blogs) then why not drop me a line?

Our projects cover a wide variety of areas, looking back over the past 8 months some of the more interesting bits of work have been:
  • A client server system for audio identification, using WCF, Base4.Net with a Monorail based web front-end.
  • Rich message processing system for Seismic Technologies, a large solution that included a rich winforms based remote configuration interface, integrated IronPython scripting, heavy use of dependency injection, WSE 3.0 and IoC.
  • Library for media transformations (designed to plug-in to the SyzmkRMP product, but also for other users) - including an Audio/Video encoding library that wraps up DirectShow.Net which was open-sourced as the Splicer project on codeplex.

Starting package would be $85K + 5 weeks holiday, Pay review after 6 months.

And on the flip-side of that coin, I'm looking for additional project/product development work to take on board, so if you have a project that you think would benefit from our unique set of skills and experience and a team of developers with a focus on innovative solutions, drop us an email.
posted @ Friday, February 23, 2007 5:54:05 AM (New Zealand Daylight Time, UTC+13:00)    Comments [2] | Trackback |
 Thursday, February 22, 2007
The whole house reverberated last night... not too impressive, but strangely odd... I figured it was probably an earth quake, but thats none too common in Auckland, so I also figured it might've just been a a really large truck, or perhaps a car exploding ;o)

... but turned out it was an earth quake...

Which got me to thinking, I haven't got any survival instincts when it comes to earth quakes ... I'd probably just stand around going "wow, never seen this before" as the roof collapsed on top of me, I probably wouldn't even think to save my laptop :P

Lets hope a bigger one isn't to follow!

posted @ Wednesday, February 21, 2007 7:17:15 PM (New Zealand Daylight Time, UTC+13:00)    Comments [3] | Trackback |
 Tuesday, February 20, 2007
Came across a short piece I wrote about IronPython while looking for something else - it was in response to some questions from Kathleen Richards in September of last year for Redmond Developer News (which I think was for this Article, though none of the content made it in - cest la vie).

At any rate, I figure I might as well post it here, it may be of use to someone... somewhere... who could say?  Looking over it briefly I'm not even sure I agree with some of the points I made any more :P


IronPython Article


How are you using IronPython?

At Syzmk (http://www.syzmk.com/) we are using IronPython as a rich embedded scripting language within our core product, we expose a large part of the .Net server engine (written in C#) to the IronPython runtime, and offer key extension points which can be hooked into with python code – we chose python because the language is rich, dynamic and doesn’t suffer from the verbosity that most of the compiled languages do.   At the moment we are moving beyond using IronPython as just an embedded scripting language and are evaluating how best to implement a number of domain specific languages in it for our server, firstly around the business rules and behavior of our application’s core logic, and secondly for performance and diagnostic evaluation and control of the underlying server platform.

Why did you choose this implementation over C python or Jython or other dynamic languages?

IronPython was attractive because of its first class support for .Net types and especially its excellent support for delegates (and because there wasn’t any marshalling) – we were attracted to the python syntax and language structure, more than support for the standard python libraries, so the compatibility sacrifices that were apparent with many C Python libraries, especially during the beta, were of little consequence to us, especially as IronPython has full access to the base class libraries (BCL).

What types of applications are you building?

The core application we have used IronPython for is a server technology, the “Rich Media Processor” (working title) – it’s in production, but has only been going to market for the last 6 months.   Effectively you can place it into an organization as a front end processor for rich and largely unstructured messages (think Audio, Video, Email, SMS and MMS messages from phones, images dumped from digital cameras, security camera feeds etc) with the end result being a structured and conforming set of messages and rich content (appropriately formatted images, videos, audio etc) suitable for passing onto line of business systems, or a product like biz talk.

When dealing with transforming this kind of content, python (and IronPython) is a great language to augment the message transformation process – strong string support, access to all the functionality of our underlying application and it’s easy to develop and deploy – IronPython never seems to be working against us, I could never claim the same for any scripting language I’ve implemented into a product before.

Does the .NET environment offer any advantages?

Yes, I think it offers serious advantages for Python (access to the BCL!), developers and customers.

First off the business case for building .Net applications is immediate within our home country of New Zealand, customers are generally expecting to host Microsoft tools and solutions, and our IT industry is geared towards this expectation, there is an implied trust which is worth taking advantage of.

Business cases aside however I think the .Net platform is very engaging for us, our company has a love for technology, and in the last few years the .Net platform has been satisfying that need very well - it offers stability, security and productivity increases that we can’t find elsewhere (and certainly not in an unmanaged language), also the language-agnostic approach and ability to build dynamic languages (like IronPython) in the CLR make the choice all that simpler.

Disadvantages?

We haven’t really discovered any disadvantages with .Net or our approach, IronPython does everything we need and then some, as does the .Net platform – however I think it might be some time yet before dynamic languages on the CLR (or any language other then VB.Net or C#) will be acceptable recommendations from the consulting masses – perhaps more a reflection on the lack of education and published case studies I think.

For instance we already have languages competing with C# on the .Net platform, such as Boo (http://en.wikipedia.org/wiki/Boo_programming_language), which offer some advantages over the current version of C# and are very suitable for building domain specific languages (DSL’s) – but I believe in many bespoke development houses it would be very hard to get buy-in for using these languages in upcoming projects, even if they will save time and money or just be a better fit for their problems.

Do you think dynamic, object oriented (scripting) languages (Ruby, Python) will start to play a larger role in enterprise development?  

I think the short answer is yes, the languages are often just a catalyst for methodologies and practices (such as functional programming, or the ruby on rails web development approach) – the elegance, simplicity and speed at which dynamic language guru’s can deliver results is enviable for a lot of us who have cut our teeth on C++ & Java and known the other end of the spectrum.

If I am in a corporate environment should I be looking into these languages?

I think at this point it should not be on the top of your list – if you’re a Microsoft shop, or in an environment dedicated to employing solutions on top of Microsoft technologies then .Net 3.0 should be your key focus - however I think it’s certainly worth having a few dynamic language books at your disposal (perhaps on the bedside table), they make for compelling reading, and will get your initial buy-in, so you feel comfortable considering a dynamic language on the .Net platform as a good idea.

That said, if you’re not a Microsoft shop, and particularly if you are committed to open-source technologies I would look seriously, probably first at Ruby, it’s very engaging story – though of course you can run IronPython on Mono with a little bit of tweaking  … and IronRuby is getting better every day.

What are some of the key issues from an application development standpoint?

I can only talk from the perspective of deploying IronPython as a scripting engine, hosted within another application, though some of these points will probably apply elsewhere, I think it all comes down to one thing -  being prepared.

First off, you must change your point of view and adapt some of your practices, as they will confound you with the introduction of a scripting language that has access to your own .Net classes.  As you develop classes, try them on for size and make sure the selected scripting language doesn’t have trouble accessing them – for instance heavily overloaded .Net methods in IronPython can be a recipe for frustration later on, same goes with using multiple out or ref parameters – that’s not to say IronPython can’t access them, just that it’s awkward and unpleasant (something your scripting language should not be).

Second to this is security – dynamic languages effectively introduce a surface area to your application that didn’t exist before – our server allows configuration (including iron python scripts) to be applied via a web service – you want to make absolutely sure there is sufficient trust between endpoints, and don’t repeat mistakes of the past with other scripting languages (think injection attacks).

posted @ Tuesday, February 20, 2007 8:56:47 AM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |
 Sunday, February 18, 2007
It seemed a long time coming, but finally Rhino Mock's 3.0 is available, which of course also means Dynamic Proxy 2 has made it to that sweet generic method support nirvana as well :)

I don't know where I'd be without these tools, I haven't done a .Net project without them in the last couple of years... in fact it's fueled my reluctance over the last couple of years for returning to bespoke development at any NZ dev shop which might dictate other (crappier) alternatives ;o)

I also noticed that mono is getting it's C# 3.0 support slowly sorted... Extension methods are in, as is some Lambda support... I need to sit down and spend some time thinking about how I should go about unit testing some of this stuff, it's on my list of "testing" things to do right after getting to grips with RhinoMocks 3 and perhaps writing another blog entry on mocking Base4 with all the new "goodies" - I need to do a monorail/base4 website for another little venture, so it's probably as good a time as any.

Went for a swim at Omaha today... just can't get enough of the beach this year - John Campbell turned up at the same time we did, there's only so many "Not in front of John" jokes I can handle in one day... or a life time ;o)
posted @ Sunday, February 18, 2007 6:11:28 AM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |
 Tuesday, February 13, 2007
Found myself writing a simple class for implanting "trial" logic for a client (as in you have 30 days left of your trial etc.) ... it relies on the current date and time, and so you can never really be assured your tests are robust unless you can control the current date & time within the test fixture (in fact any time you find yourself writing DateTime.Now alarm bells should be going off... even worse is logic based on DateTime.Now where it's evaluated more the once for a single function).

In the past I've generally Implemented something like an "IClock" interface, which would have a method like "DateTime GetCurrentTime()" or whatever seemed appropriate to the situation... but I decided to go with the lightweight solution of delegates instead in the morning, if only because I was being lazy I didn't see the need for creating an entire interface for such a trivial requirement... so we have:

private DateTime _trialExpirey;

private int _maxExecutions;

private TimeSpan _trialDuration;

private Func<DateTime> _nowFunction;

 

public TrialUpdater(DateTime trialExpirey, int maxExecutions, TimeSpan trialDuration)

    : this(delegate { return DateTime.Now; }, trialExpirey, maxExecutions, trialDuration)

{

}

 

public TrialUpdater(Func<