Programming in C#, Java, and god knows what not

Microsoft’s All In One Code Framework

Browsing through one Belgian guy’s blog I found news about Microsoft’s All In One Code Framework.

In short, it is a site where you should be able to find best practice code samples. You can even make a request for some sample that you need. Of course, not all requests will be granted but interesting and much sought code should appear there eventually.

Of course, anybody can upload their code sample for any request and thus take some load off poor Microsoft guy who got writing samples as a task. :)

It is interesting idea, but let’s wait whether usefulness/noise will be better than rest of Internet.

Directory.Move Is Case Insensitive

In order to rename file one would use code that looks something like this:

File.Move("file1.txt", "file2.txt");
File.Move("file.txt", "FILE.txt");

Both lines work without any issue, just as you would expect it.

What happens when we do rename with directories (aka folders):

Directory.Move("dir1", "dir2");
Directory.Move("dir", "DIR");

First line works but second one raises IOException (Source and destination path must be different). For some reason Directory.Move does case insensitive checks. For this to work we need slightly different code:

Directory.Move("dir", "DIR.somereallyunexpectedtext");
Directory.Move("DIR.somereallyunexpectedtext", "DIR");

This code first renames directory to temporary name and then renames it to desired one. Tricky code not shown here is exception handling. Either Directory.Move can fail and thus we would need code like this:

Directory.Move("dir", "DIR.somereallyunexpectedtext");
try {
    Directory.Move("DIR.somereallyunexpectedtext", "DIR");
} catch (IOException) {
    Directory.Move("DIR.somereallyunexpectedtext", "dir");
} catch (UnauthorizedAccessException) {
    Directory.Move("DIR.somereallyunexpectedtext", "dir");
}

For any failure cause we need to do rollback (renaming it back to original name from intermediate one). And worst thing is that, if second rename fails, there is probably no chance in rollback working anyhow. Most common solution? Just forget about handling exceptions and rollback between those two renames. Probability is on your side that, if first operation passes, other will pass too.

Canceling Dialog

As I made review of one application I got reminded of one common error. Theory of cancel button is easy enough. It is enough to set button’s DialogResult to Cancel and form’s CancelButton property to that button and form will close automatically. However, what to do if we need to cancel some background operation?

More than once I saw cancel code inside of cancel button’s Click event. This is WRONG. If you are wondering why, just take a look at your application state when somebody decides to close dialog via small red button in upper right corner instead of pressing cancel button. All that carefully crafted cancel code never gets chance to execute.

Solution is trivial. All your code should go inside of either FormClosing or FormClosed event. These events get triggered whatever way you do form cancelling:

    private void Form_FormClosed(object sender, FormClosedEventArgs e) {
        if (backgroundWorker.IsBusy) { backgroundWorker.CancelAsync(); } //just an example of cancellation code
    }

Cancel button should NEVER have any code in it.

P.S. Whether to use FormClosing or FormClosed is mostly matter of philosophical discussion that I intend to leave for other post.

Select or Focus, Which One to Use?

Quite a few Windows Forms controls have both Focus() and Select() methods available. This presents unique challenge - which method to use?

While they both offer same result (ok, almost same) there is subtle difference. Focus is intended only for control authoring, e.g. when you have some composite UserControl. For all other scenarios, Select should be used. Probably nothing bad will happen (or maybe some kittens will die) if you use Focus on controls that behave. However, small differences might force you to use Select on some other controls and that leads to code with uses Focus half of time and Select another half. Kinda hard to read.

It might improve actual readability if Select is used all the time.

Nullable Fields in Database

Duty of every decent Data Access Layer is to convert data types that we have in database to data types of our favorite programming language (C# in this case). And this is easy in case of “normal” data types. Great example here is humble integer. Database and C# have 1 to 1 mapping here. It is as easy as “var x = (int)dr["field"];”.

However, database can have one more trick up it’s sleeve. Every data type can be “nullable”. That is, it can be integer but it can also have special state which signifies lack of data. C# also has same possibility with his nullable types. Intuitive code “var x = (int?)dr["field"];” will not work properly.

While we can make wrapper function for any nullable data type that we need, there is simpler way. All that we need is:

private static Nullable<T> ToNullable<T>(object value) where T : struct {
    if (value == null) { return null; }
    if (System.Convert.IsDBNull(value)) { return null; }
    return (T)value;
}

Now conversion can proceed with “var x = ToNullable(dr["field"]);”. That doesn’t look that ugly, does it?

Detection of Executing Program in Inno Setup

Illustration

When upgrading your application it is very good practice to let your setup program know whether your application is running. This way setup will tell you to close your application instead of requiring Windows restart.

Solution comes in form of Mutex synchronization primitive. Application will create it and hold it until it is closed. If setup notices that application already has mutex under control, it will “complain” to user. It is then user’s task to close application. It is not as comfortable as closing application automatically but it does the job.

Since we need a global mutex for this purpose, we should not use something that could get used in other application for other purpose. To me best format of name is MyCompany_MyApplication. It is highly improbable that anybody else would use it. If you want to be (almost) sure getting random string is also a possibility.

For this to work we need to tell InnoSetup which mutex we plan on holding:

[Setup]
...
AppMutex=Global\MyCompany_MyApplication
...

In application we need to use same Mutex name:

namespace MyNamespace {
    internal static class App {
        private static readonly Mutex SetupMutex = new Mutex(false, @"Global\MyCompany_MyApplication");

        [STAThread]
        internal static void Main() {
            //do some great stuff.

            Application.Run(new MainForm());

            SetupMutex.Close(); //notice that it HAS to be after Application.Run
        }
}

P.S. Why do we MUST put SetupMutex.Close() after Application.Run() is exercise left to user. I will just note that it has something to do with garbage collection.

P.P.S. While this was written with InnoSetup in mind it is also applicable to virtually all setup systems out there.

Java Loves MSVCR71.dll in 64-Bit

Illustration

As I installed DevMail on fresh 64-bit Windows system, I was greeted with “The program can’t start because MSVCR71.dll is missing from your computer. Try reinstalling the program to fix this problem.” Although program started normally when I dismissed error message I found it annoying.

After some troubleshooting I narrowed issue on Java. And I found pretty good explanation of this problem. After knowing this, solution was simple.

I went into “C:\Program Files (x86)\Java\jre6\bin” folder and copied “msvcr71.dll” from there to DavMail’s application folder (“C:\Program Files (x86)\DavMail”). This way DavMail found his dll and everybody was happy.

P.S. It was interesting to see that DavMail developers had more than one ticket open on this subject. They closed them with solution “reinstall Java”. That solution is invalid. Real solution would be to include this dll with installation.

P.P.S. I found it annoying and idiotic of Sun Oracle to remove this bug from their bug database. That bug used to exist (and thus we know that it’s ID is 6509291) but they removed it. Only reason that might fit Sun’s Oracle’s FAQ is “security reasons”. How this applies to this situation is anybody’s guess.

Mercurial Summary

I noticed that I wrote quite a few posts regarding Mercurial and they are spread all around blog. This post will give just a quick summary.

Server:

Converting:

Tricks:

Clients:

Custom Defined Identities

I love identity columns in database. They make great primary key for almost any table. Only situation where I hate them is when I need to import data with foreign keys. You see, you cannot manually define identity column. Or can you?

Let’s imagine SQL Server table (named SomeTable) with two columns. First one will be Id (int, identity and primary key) and second one will be SomeText (nvarchar). Then let’s try to insert some data:

INSERT INTO SomeTable(Id, SomeText) VALUES(1, 'Some text');
Msg 544, Level 16, State 1, Line 1
Cannot insert explicit value for identity column in table 'LookupDiagnosis' when IDENTITY_INSERT is set to OFF.

Like all good error messages, this one already offers solution. We need to manipulate IDENTITY_INSERT option. Let’s try again:

SET IDENTITY_INSERT SomeTable ON
INSERT INTO SomeTable(Id, SomeText) VALUES(1, 'Some text');
SET IDENTITY_INSERT SomeTable OFF

With this little trick importing data with identity columns becomes much easier.

P.S. Just remember that you cannot have IDENTITY_INSERT set on more than one table at a time.

P.P.S. This option is also great for filling gaps left in identity column by deleted rows or canceled transactions.

Moonlight 4

Illustration

Lately big part of my day is working on Linux. Usually there are no issues. As long as I stick to web applications I am mostly ok.

Here comes the problem. For their PDC conference Microsoft decided to use Silverlight. Since I wanted to check a video or two and Microsoft is proud of Silverlight being supported on every possible platform I thought that everything would work.

Well it doesn’t.

P.S. Should I say that Flash videos work without issues on both Windows and Linux?