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

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?

Multi-mercurial

I believe that ideal setup for Mercurial is one project per repository. Most of time this is really good setup but occasionally it will cause problems. Whenever I need to do same thing on multiple repositories (e.g. push) there is an issue. Better said, there was an issue before I created HgAll script.

Script is written in PowerShell and does two things. First it traverses all directories bellow current (or defined) one and finds all mercurial repositories. Then it forwards whatever is on command line as parameter to hg command line utility. In effect it executes same command to each repository it finds.

HgAll [StartingFolder] [commands]

HgAll C:\Source summary
HgAll push all

First example will start search from C:\Source and execute “hg summary” command for any Mercurial folder found. Second example will start in current directory and execute “hg push all”.

You can download script here (or take a peek at source bellow):

$StartupLocation = (Get-Location -PSProvider FileSystem).ProviderPath

$Folder = $Null;
$Command = ""
foreach ($arg in $args) {
    if ($Folder -eq $Null) {
        if ((Test-Path -Path $arg -PathType Container) -eq $True) {
            $Folder = (Resolve-Path -Path $arg).Path
            $Command = ""
        } else {
            $Folder = $StartupLocation
            $Command = $arg
        }
    } else {
        if ($Command.length -ne 0) { $Command += " " }
        $Command += $arg
    }
}

if ($Command.length -eq 0) {
    $Command = "summary"
}

function Traverse([string]$path) {
    Write-Debug $path
    $dirs = Get-ChildItem $path | Where {$_.psIsContainer -eq $true}

    if ($dirs -ne $Null) {
        foreach ($dir in $dirs) {
            $hgsubdir = Join-Path -Path $dir.FullName -ChildPath .hg
            if ((Test-Path -Path $hgsubdir -PathType Container) -eq $True) {
                $hgdir = $dir.FullName
                if ($Command.length -ne 0) {
                    Set-Location $hgdir
                    Write-Host
                    $result = Invoke-Expression "hg $Command 2>&1"
                    if (($LASTEXITCODE -ne 0) -or (!$?)) {
                        Write-Host $dir.Name
                        foreach ($line in $result) {
                            Write-Warning $line
                        }
                    } else {
                        Write-Output $dir.Name
                        foreach ($line in $result) {
                            Write-Host $line
                        }
                    }
                }
            } else {
                Traverse($dir.FullName)
            }
        }
    }
}


try {
    Traverse($Folder)
} finally {
    Set-Location $StartupLocation
}

Not Your Normal Random

Illustration

When I test with random data I usually tend to use normal distribution. This particular time I didn’t want that. I wanted to simulate sensor readings and that means that I cannot have values going around all willy-nilly. I wanted sensors to read their default value most of time with occasional trips to edge areas. This is code I ended up with:

private static double GetAbnormalRandom() {
    double rnd = Rnd.NextDouble();
    double xh = 0.5 - rnd;
    double xs = xh * xh * 2;
    double x = 0.5 + Math.Sign(xh) * xs;
    if (x < 1) { return x; } else { return 0.5; }
}

2) This is just standard random number. Minimum value is 0 and maximum is LOWER than 1 (it can also be written as [0,1)).

3) I than moved this number to minimum of -0.5 and maximum lower than 0.5 ([-0.5,0.5)).

4) In order to maximize our mean value, I decided upon square function. It gives us number ranging from 0 to less than 0.5 (0.52 gives 0.25 and multiplication by 2 moves this back to 0.5).

5) Everything could stop here sine I have my distribution already available in step 4. However, I wanted to get everything back into [0,1) range. It is just matter of adding 0.5 to whatever number we got in step 4. Sign operation is here to ensure that half of numbers go to less than 0.5 and half of them go above.

6) Of course all this math is causing rounding to our floating point numbers. In rare occasions that can cause our step 4 to generate positive range number that is equal to 0.5. It is very rare (approximately 1 in 1000000) and we can just add it in middle.

And this is it. Function will most probably return values around 0.5 with sharp drop in probability for values further toward edge (see graph).

For full code alongside some statistics you can download source code.

ToolStrip as Main Menu

Let’s take small project as an example. You need two or three options and you cram everything as root menu item. Since you like your users and your users like pictures, you additionally create toolbar with same options. Final toolbar has one-to-one mapping with menu. Now question is why do we need menu in first place?

Personally I see only one reason - keyboard accessibility. Toolbar might be nice but it will not allow us to use pure keyboard interface in order to select items. However, solution is simple. First we set KeyPreview=true on form itself and then we just handle Alt key:

private void MainForm_KeyDown(object sender, KeyEventArgs e) {
    switch (e.KeyData) {
        case Keys.Alt | Keys.Menu: {
            menu.Select();
            menuNew.Select();
            e.SuppressKeyPress = true;
            e.Handled = true;
        } break;
    }
}

This code acts upon Alt key press. First we need to select ToolStrip control and then we select first item (New, in this case) within it. If we just use Select on item it will look same, but keyboard arrows will not move selection between items.

Downside to this is handling shortcut keys. While MenuItem will allow us to set Ctrl+N as shortcut key same is not true for ToolStripButton. All shortcuts should be handled explicitly now (within MainForm_KeyDown event):

···
case Keys.Control | Keys.N:
    menuNew_Click(null, null);
    e.SuppressKeyPress = true;
    e.Handled = true;
    break;
···

Full code example is available here.

Not All Files Can Be Embedded

Quite a lot of helper files needed for average applications are best stored as resource. This way separation of data and code is kept on logical level but everything gets stored in one executable so nothing can be lost.

In order to make some file resource only thing needed is selecting “Properties” from context menu and setting “Build Action” to “Embedded Resource”. Reading this from code is equally easy (assuming program is called MyProgram and resource file is called Test.txt):

Stream myStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyProgram.Test.txt");

It is easy as it can be and I was very surprised when I could not get this to work. I added file “File.hr.xml” to project and I embedded it correctly but GetManifestResourceStream method returned null for it. Documentation says that this can only happen when resource is not there and this was impossible in my case.

In order to confirm this I looped through all resources I had embedded:

foreach (string name in Assembly.GetExecutingAssembly().GetManifestResourceNames()) {
    Debug.WriteLine(name);
}

To my surprise documentation was correct, my file simply wasn’t there. However, in my bin folder there was subfolder named “hr” with “MyProgram.resources” file inside.

Then it hit me. Problem was in multi-dotted extension with valid language code as first part. These files are understood by Visual Studio as being language specific and reading them from another culture is not possible (ok, it is possible but not easy).

Since I really wanted this resource to be available regardless of localization, solution was simple. I just renamed file to “File-HR.xml” and it magically appeared in resource list.

Mercurial Over Both Http and Https

My last post about Mercurial left us with Mercurial server listening to https-only requests. This is probably best solution security-wise but there might be valid reasons for having it on http also (e.g. performance within local network).

Solution lies in editing “/etc/apache2/sites-available/hg” to have two configurations - one for http and one for https:

NameVirtualHost *:80
NameVirtualHost *:443

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /srv/hg/cgi-bin
    <Directory "/srv/hg/cgi-bin/">
        SetHandler cgi-script
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>
    ErrorLog /var/log/apache2/hg.log
    <Location />
        AuthType Basic
        AuthName "Mercurial"
        AuthUserFile  /srv/hg/.htpasswd
        Require valid-user
    </Location>
    RewriteEngine on
    RewriteRule (.*) /srv/hg/cgi-bin/hgweb.cgi/$1
</VirtualHost>

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    DocumentRoot /srv/hg/cgi-bin
    <Directory "/srv/hg/cgi-bin/">
        SetHandler cgi-script
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>
    ErrorLog /var/log/apache2/hg.log
    <Location />
        AuthType Basic
        AuthName "Mercurial"
        AuthUserFile  /srv/hg/.htpasswd
        Require valid-user
    </Location>
    RewriteEngine on
    RewriteRule (.*) /srv/hg/cgi-bin/hgweb.cgi/$1
    SSLEngine on
    SSLOptions +StrictRequire
    SSLCertificateFile /srv/hg/https.crt
    SSLCertificateKeyFile /srv/hg/https.key
</VirtualHost>

After quick Apache restart your Mercurial will answer both http and https requests.