Author Archive

Single instance application with C#

Friday, April 24th, 2009

If you’re developing a winforms application with VB.NET you can set a checkbox in the designer to have a single instance application. This option is not available to C# developers but since language does not matter in the .NET space you can just use the same classes the VB.NET designer uses.

By subclassing WindowsFormsApplicationBase you can get the same behaviour. The class can be found in the Microsoft.VisualBasic.ApplicationServices namespace.

public class SingleInstanceManager
      : WindowsFormsApplicationBase
{
 
    public SingleInstanceManager()
    {
        IsSingleInstance = true;
        EnableVisualStyles = true;
        ShutdownStyle = ShutdownMode.AfterMainFormCloses;
    }
 
    protected override bool OnStartup(StartupEventArgs e)
    {
        return true;
    }
 
    protected override void OnCreateMainForm()
    {
        base.OnCreateMainForm();
        MainForm = new MainForm();
        HideSplashScreen();
    }
 
    protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
    {
        base.OnStartupNextInstance(eventArgs);
        MainForm.Focus();
    }
 
    protected override void OnCreateSplashScreen()
    {
        base.OnCreateSplashScreen();
        SplashScreen = new SplashForm();
    }
}

Change your Program.cs to use this new class.

[STAThread]
static void Main()
{
    var manager = new SingleInstanceManager();
    manager.Run(new string[]{});
}

Using attributes with Spring.NET to configure your application

Friday, April 24th, 2009

When using Spring.Net you end up editing xml files to wire everything together. While something like fluent Spring.Net would be very nice to have, some of the xml authoring can be solved by using attributes. As sample I’ll use a real life example where I implemented it.

I had to add reporting to an application which consists of different modules. Depending on the license of the user he’d have a contacts module, a document management module, tasks, etc. The user would select the contents of his report and then fire up the designers to choose fields, order or group them, etc.

The end-user components we use are quite powerful so I only had to find a way to get the content into the report component as a dataset. Normally I keep away from using datasets but in this case it’s allowed. Note that I’m not using data adapters and other stuff, I just transform my rich object model into a flat dataset.

Each module writes an entitymapper for all of the entities that can be used as reporting source.

[EntityMapper(EntityType = typeof(ContactDto))]
public class ContactMapper
    : EntityMapper
{
    public override DataSet MapToDataSet(IEnumerable<ContactDto> entities)
    {
        DataSet dataSet = new DataSet();
        //fill with data
        return dataSet;
    }
}

I only wanted to add the object definition to the configuration specific for this module. I didn’t want to edit the config for reporting module. It should just pick all the mappers up and use them when entities of that type are handed to it.

The solution for this is using an IObjectPostProcessor to inspect everything that is configured in your container and do some additional logic.

public class MapperPostProcessor
    : IObjectPostProcessor
{
    private readonly Type attributeType;
 
    public MapperPostProcessor()
    {
        attributeType = typeof (EntityMapperAttribute);
    }
 
    public DataSetMapper Mapper
    {
        get;
        set;
    }
 
    #region IObjectPostProcessor Members
 
    public object PostProcessAfterInitialization(object instance, string objectName)
    {
        object[] o = instance.GetType().GetCustomAttributes(attributeType, true);
        if(o.Length == 1)
        {
            var attribute = o[0] as EntityMapperAttribute;
            var entityMapper = instance as IEntityReportMapper;
            Mapper.RegisterMapper(entityMapper, attribute.EntityType);
        }
        return instance;
    }
 
    public object PostProcessBeforeInitialization(object instance, string name)
    {
        return instance;
    }
 
    #endregion
}

Any postprocessor in your Spring context is automatically picked up by Spring and the methods will be called on the appropriate time. In this implementation I check every instance that is handed to the PostProcessAfterInitialization method for my own attribute, if it’s present I register it to my mapper manager for the specified type. For more info about this you should check out the documentation.

Out of the box Spring.NET has some of these already for you. For instance you can put the [Required] attribute on the properties that need to have a value after they have been constructed. If at that time they haven’t been initialized you’ll get an exception.

Introducing RovingContacts

Saturday, April 18th, 2009

It’s been in the pipeline for quite some time, but it’s finally here RovingContacts . It’s the first of a series of products that will give your life in the digital era a bit more structure and let you be more productive. RovingContacts allows you to input or import your contacts, see how they are related, add fields that are important to you, see their location on a map, get driving directions, create reports or greeting cards for that matter, and much more.

rovingcontactsdetailsmall

This first version does not mark the end of development on this new platform. RovingContacts and all the other suites are still under active development. We are constantly reworking and refining existing features while adding new and exciting functionality that will help you get your work done. One very attractive feature is being able to synchronize your contacts to pretty much any platform in the world. Yes any platform, that includes your cellphone, Plaxo, MS Outlook, AOL, Windows Live, Google Contacts,… you name it, we sync it.

This is the start of a very interesting journey for us, so jump aboard and go download a copy! 

rovingcontactsoverviewsmall

Moving WPF control to class library

Wednesday, April 15th, 2009

I recently made my first WPF control. It’s just a simple control to show media files. After experimenting with it and seeing all was ok I moved the files to the main project where it would reside in a class library project.

It stopped building with the exception: ‘Library project file cannot specify ApplicationDefinition element’.

To anyone with 15 minutes of WPF experience this does not say a lot. Even after searching the web I couldn’t really understand what was going on but this thread did set me on the right track. You need to set the build action of your WPF control to ‘Page’.

wpfusercontrol

Load event not fired when using the WebBrowser control

Monday, March 16th, 2009

Today I had to add a way so that a webpage could be displayed with each form in a WinForms application. Doesn’t sound that hard now does it? We’ve developed our own little MVC/MVP framework, so in order to enable this behaviour I just had to create a usercontrol, throw a webbrowser control on it, some logic and done. Our framework automatically detects the control and the end user can add these controls at run time to any form he wants.

The logic I had added to the control detected if a certain file had been clicked, since these had to be handled by the application and not by the webbrowser, really straightforward stuff. In the load event of the control I registered to the necessary events which would trigger my code. The only problem being that the load event was never fired. I looked at my code again, maybe 20 lines or so including brackets and braces, and didn’t see anything wrong with it. I then looked to some other controls  my colleagues and I had already written in the past to see if I did something wrong but couldn’t see any big difference. Time for some debugging!

With breakpoints all over the place it was clear that the constructor of my form and presenter was being called and the event subscription was being done but the Load event somehow was never triggered. I went over and over the code again and again but really couldn’t get my head around this. Why on earth wasn’t the event being fired. I even went away from the compiler generated properties back to the old fashioned getters and setters with a field just to make the code look more like all the other controls but nothing worked.

Until I removed the webbrowser control from my usercontrol. Now all of a sudden my load event was being fired, the culprit was found!

So somehow when you use the webbrowser control, your load event, and who knows what else, is fubar. I only found one usable search result on the internet, here. And the workaround mentioned works like a charm, make your webbrowser control invisible until after the load event :-) . Well in my case the presenter calls NavigateToUri(uri) on my view and in that method I set the visibility of the webbrowser to true. Smells like a bug to me but at least now it’s working, too bad it took 4-5 hours.

Custom username password validator with Geneva

Thursday, February 5th, 2009

I had been busy for hours to get my custom username password validator working with the Geneva Framework when I turned to the MSDN forum to look for help. Someone was kind enough to point me to this article by Yossi Dahan which solved my problems.

I’ve modified one of the samples that is installed with the Geneva Framework. It relies on having two certificates, one with CN=localhost and one with CN=STS.

Download

Safe Cross Thread UI Access

Wednesday, May 21st, 2008

When you have multiple threads running in your application and have a user interface you’ll eventually run into the fact that UI elements are only allowed to be called from the same thread they are created in. The fast workaround for this is to set the CheckForIllegalCrossThreadCalls property of your controls to false but since we’re all good developers we want to solve this in a clean way.

There is an interface to track this behaviour called ISynchronizedInvoke which defines all the methods you need, this interface is implemented by the UI controls. You need to see if the property InvokeRequired is true and call Invoke (or BeginInvoke) to make your call thread safe. I used to declare a delegate for each different method signature I encountered since the Invoke methods take a delegate as argument. But there is a much more elegant way by using the MethodInvoker delegate and an anonymous delegate as you can see below. This prevents you from declaring a lot of delegates just for making your calls thread safe. This is illustrated below by a method in a presenter which updates my view.

public void IncomingMessage(ChatMessage msg)
{
    if (m_ChatView != null && m_ChatView.InvokeRequired)
    {
        m_ChatView.BeginInvoke(new MethodInvoker(delegate
        {
            IncomingMessage(msg);
        }), new object[] { msg }); return;
    }
    m_ChatView.DisplayMessage(BuildIncomingDisplayMessage(msg));
}

Mystery tab #13119

Monday, April 14th, 2008

Since a couple of weeks I had this #13119 tab in the toolbox of Visual Studio. The only way I found to fix this was to go into C:\Documents and Settings\[UserName]\Local Settings\Application Data\Microsoft\VisualStudio\9.0 folder, replace [UserName] with your username, and delete the four files which have Toolbox in their name (toolbox.tbd, toolboxIndex.tbd, toolbox_reset.tbd, toolboxIndex_reset.tbd). Visual Studio regenerates these when you start it up. Full thread on MSDN can be found here.

Buildserver upgrade

Monday, April 7th, 2008

We recently started the move from visual studio 2005 to 2008 and since then our buildserver has had problems with those upgraded projects.

The first error I ran into was: File format version is not recognized.  MSBuild can only read solution files between versions 7.0 and 9.0, inclusive. Our server runs CruiseControl v1.3.0.2958 which by default targets the 2.0 framework, so you need to direct your MSBuild task to the new 3.5 version. You do this by using the executable node illustrated below:

<msbuild>
<executable>C:WINDOWSMicrosoft.NETFrameworkv3.5MSBuild.exe</executable>
...
</msbuild>

Second error: The imported project “C:Program FilesMSBuildMicrosoftVisualStudiov9.0WebApplicationsMicrosoft.WebApplication.targets” was not found. To fix this one you need to look on your development machine for that file, it’s on the same location as stated by the error if you’re using a regular install. Then go to your buildserver and recreate the same folder structure there and copy the file.

Third error: C:WINDOWSMicrosoft.NETFrameworkv3.5Microsoft.Common.targets (1734,9):  error MSB3091: Task failed because “LC.exe” was not found, or the correct Microsoft Windows SDK is not installed. The error message is larger than I’ve put here since it gives 4 ways to solve it. The easiest and probably fastest way to solve this is to download the Windows SDK for Windows 2008 and install it on your buildserver, you can find it here. It is an iso file of 1.3 GB, so make sure you have a fast connection.

Now your server has been successfully upgraded ;) .

Cleanup Folder with SDC Tasks Library

Monday, April 7th, 2008

I had to automate the deletion of the contents of a folder for one of our projects in the buildserver, one google later I ran into the SDC Tasks Library (2.1.3009.0) which had just that. The pdf file included described how to make their library available in your build script, I followed the instructions but kept running into build errors. The Cleanup task was not found by MSBuild, turned out I needed to add a trailing backslash to the path name of the TasksPath property. The final configuration is:

<!– SDC MSBuild Tools –>
<PropertyGroup>
<TasksPath>$(MSBuildExtensionsPath)\Sdc\</TasksPath>
</PropertyGroup>
<Import Project=“$(TasksPath)\Microsoft.Sdc.Common.tasks“/>
<!– SDC MSBuild Tools –>

But even with this now corrected the Cleanup folder task was not found, again I opened up their tasks file with notepad and searched for the Cleanup task, I couldn’t find it. Hmm, maybe I’m going blind so let’s use ctrl+f. Again no results. So I edited the file and put this entry to the list of tasks:

<UsingTask AssemblyFile=“$(TasksPath)Microsoft.Sdc.Tasks.dll“ TaskName=“Microsoft.Sdc.Tasks.Folder.CleanFolder“/>

Ran MSBuild again, and now successfull. For anyone who doesn’t want to edit the file, I’ve attached it.

Microsoft.Sdc.Common.tasks (40,21 kb)