Aggressive Installers

Aggressive installer is just like aggressive marketing (or guerilla marketing) - it uses inconvenient way to promote some other products. This is what I've been thinking for last few times I've been installing Java updates. When you click on that orange icon notifying you that update is available, you get an installation wizard which "will guide you though the setup process". At some point you are prompted to install OpenOffice or Google Toolbar along with Java, although I don't understand how they are related and why it is already selected by default. As I do not need nor use any of those tools, I unselect it and continue. But imaging an average user, who knows nothing about computers and only uses his own for e-mails or researching online. Speaking of such user, I have several perfect examples - one of them is my mother, who is a psychiatrist and often searching Google (or different online resources) for something she needs. Second is my girlfriend, who just uses mails, sometimes online in-browser games and chats.

Now what they would do when they are going though setup? Right, they just click Next button a couple of times and vu-a-la, the system is up-to-date. With an addition to useless (to my mom and g-friend) OpenOffice and Google toolbar, which make Internet Explorer look like garbage collection and Word documents are now opened in strange-looking application that none of my relatives know about.

What next? Maybe wizard will prompt to install Linux instead of MS Windows? Why not? What is the difference, right? Isn't that the same tactics that EU and Open Source organizations claimed to be used by Microsoft? Microsoft at least added they own software, which is an added value to operating system as a whole - Windows Media Player is an example, without it the system would not be able to play media files, but what we see here? Some organization sneaks another software which adds another piece of junk and makes my system unstable. And I do NOT want to say that OpenOffice or Google toolbar is a piece of junk as is. But in my environment - they do not add anything valuable and instead interfere with already installer programs, which makes them just a plain junk.

Technorati Tags: , , ,

Chinese Simplified is available for DBAdmin

Thanks to George J. Sun (web), Chinese Simplified language pack is available for Database Administrator. The ZIP file containing all languages is updated with the new file. I have to admit - I couldn't test it, as my system don't even display Chinese, so if anyone sees any problem in with the language file (not displayed properly and such), contact me or George to get it fixed :)

As a reminder - DBAdmin is a tool for online managing your MS Access databases, written by me some time ago and using plain ASP (not .NET).

Technorati Tags: , , ,

Progress bar in Janus Grid

Progress bar inside grid's cell

Janus's Grid doesn't allow custom controls inside its cells, but for my task, I had to show a progress bar on each row and was looking on how to do that. Well, I couldn't find any info apart from drawing the progress myself. Fortunately, progress bar is a simple rectangle and drawing rectangle is quite simple task. Below I'll explain how I did it. You can also download a zip file, containing sample project (you will have to have Janus GridEx installed on your system in order to be able to compile it though) - see the link at the bottom of this article.

First of all, add GridEx onto your form, create root table and columns (or retrieve from database, whatever suits your needs). Go to the column you wand to have progress bar and change its "OwnerDrawMode" property to "Cells". This will allow us to catch DrawGridArea event and create our progress bar. It's also nice to set Selectable to false on that column, since it is really not meant to be selected.

Now attach handler to DrawGridArea event and let's add some code into it. First of all, we need to find out on which column we are working on and do this by simply examining Key property of the column in event argument:

if(e.Column.Key == "Percent")
{

In my example, I have choose to name the column Percent. Now we should draw a background, which will be a simple rectangle of system's window color. You may pick another color if you want:

e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);

Next task would be progress bar bounds calculation and drawing it

int progress = (int)e.Row.Cells[e.Column].Value;

//calculate the rect to draw:
Rectangle rect = Rectangle.Inflate(e.Bounds,-1,-3);
rect.Width = (int)(rect.Width * progress / 100.0);

//now draw the rectangle:
if(rect.Width > 0)
{
    using(Brush br = new System.Drawing.Drawing2D.LinearGradientBrush(rect, Color.PowderBlue, Color.Navy, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
    {
        e.Graphics.FillRectangle(br, rect);
    }
}

As you can see, I'm using LinearGradientBrush, just because, IMHO, it looks nicer, feel free to pick any other brush (solid for example) and your own colors - this is your progress bar at the end.

Basically that's it. Now we have a working progress bar inside grid. Optionally, we can add the percentage number itself on the  bar or aside of it when the area is too small for text. Here is the code:

//draw the percentage
string text = progress.ToString() + "%";
SizeF textSize = e.Graphics.MeasureString(text, e.Font);
Color textColor = Color.White;
Rectangle textRext = rect;
StringFormat format = new StringFormat(e.StringFormat);
format.Alignment = StringAlignment.Center;
//check if there is enough room for percentage text. 
//If not, we draw text aside of progress bar and not inside it
if(textSize.Width > rect.Width)
{
    textColor = e.ForeColor;
    textRext = new Rectangle(rect.Right + 2, rect.Y, e.Bounds.Width - rect.Width - 2, rect.Height);
    format.Alignment = StringAlignment.Near;
}
using(Brush brush = new SolidBrush(textColor))
{
    e.Graphics.DrawString(text, e.Font, brush, textRext, format);
}

Finally, don't forget to set Handled property to true:

e.Handled = true;

Download sample project (for Visual Studio 2003/NET 1.1 or higher).

Technorati Tags: , , ,

When User Control or Form doesn't open in Form Editor

I was working on some project in Visual Studio 2003 with many user controls in it and suddenly, I found that I cannot open any control with Forms Editor. When I double-click on the file, it opens with CSharp code editor only. I'm still unsure how did this happen, but after looking at ".csproj" file in notepad, I have found how to fix this.

Each file in .NET project is described in separate "File" node inside project file (or "Compile" node in Visual Studio 2005/2008), like in the screenshot below:

VS2003 Project file example

Note, the SubType attribute - this is the one that helps to pick the editor. In my case, all user controls received SubType="Code" for some unknown to me reason. So I went and updated them manually to "UserControl" and reloaded the project. After that, double-clicking on control in Solution View, opened forms editor as it should be.

For Visual Studio 2005/2008, the file XML structure is slightly different - instead of File node, there is "Compile" and SubType is not longer an attribute, but an XML node - child of "Compile" node. It's really easier to just open ".csproj" file and check it by yourself.

TortoiseSVN version 1.5 - sucked

Well, I'm using TortoiseSVN at work, in conjunction with AnkhSVN - plugin for Visual Studio 2003. Don't ask me why, I do NOT like SVN in first place but this is what old projects use in the company I work in. And lately I had to do some changes in old project, so installed TortoiseSVN 1.4.x and AnkhSVN 1.0.2. This worked just fine for a couple of months but today I have decided to upgrade Tortoise to latest version.

Yes, blame me, I forgot that this is an Open Source project and they do NOT think about backward compatibility. Never. Guess what? Guys in TortoiseSVN decided to change format of their "working copy" and Ankh has stopped working because it doesn't know about the new format. Mind you, I have upgraded from version 1.4.x to version 1.5. Not from 3.0 to 10.0 and not even from 1.0 to 2.0. Damn, I wasn't suspecting such ignorance even from open source community.

Oh and BTW, there is no Ankh client for VS 2003 that can work with new format. So I'm in process of backing up projects, uninstalling new version and installing version 1.4.x instead.

Virtual Server on Windows Home Server

I'm running WHS, with 2 GB and wanted to setup a Microsoft Virtual Server on it. So I have followed a simple guide at Robert Stinnett's blog and got first host up and running - Windows 2003. As you may imagine, it installed fine, without any issue.

Next was Linux Ubuntu installation. So I have downloaded it from official site (version 8.04), copied to Home Server and created a new virtual machine. As I expected, first thing Linux did when I tried to install, is simply crashed. You may ask me why I have expected this - just because this already happened to me with one of previous versions of Ubuntu on Virtual PC. Luckily, I'm not the first one who encounter this issue, so I have quickly found a guide on how to fix this problem. After that, installation went smooth.

Other issue I had AFTER everything was installed and running fine - when I have booted Linux machine, it failed to start up because the hard disk file was being used by another program:

"The virtual hard disk "\\*****\Virtual Machines\Linux Ubuntu\Linux Ubuntu.vhd" attached to primary channel (0) of "Linux Ubuntu" could not opened with read-write access. You need read-write access to the virtual hard disk to boot a virtual machine. Another virtual machine or the Virtual Disk Manager might be using this disk right now."

Unfortunately, when I logged to server to check who is accessing hard drive file, the problem has gone. So I'm not sure if this was Virtual Server itself or maybe Home Server tried to "balance" drive and thus locked the file.

Migrated my Windows Home Server to new hardware

At home, I'm using Windows Home Server to store all my videos, photos, music and other content. I'm using it for about half year now and apart from annoying corrupted files bug (which supposed to be fixed in upcoming Power Pack 1), I'm pretty in love with it. Anyway, this is not about WHS and what I like in it, but more about migrating it to a new hardware.

When I got the system first time, I have installed it on my old computer, that was previously hosting Window XP. But the computer is about 7 years old and its getting hard and expensive to find parts for it. So I have decided to get a new inexpensive computer and finally throw out the old one. And here I was not sure on how the migration will work.

First of all - I didn't have much content, all about 200-250 GB, and I had such space on new computer, so I simply copied all content there. Sure it filled up my hard drive, but that was temporary, right? Then I plugged in new computer, with new 500GB disk, pushed WHS installation CD inside and the show began. I was asked at the beginning about preferred keyboard layout and then setup continued so I could return to Everquest II while WHS was installing.

In about hour, I checked what's up with installation and found out that everything was working fine and ready to be used. So I set my administrative password (which BTW is not GOD or SEX or PASSWORD), added my home users using WHS console and was looking for a way to reconnect my client machines to new server. Thus I have found, that simply executing Discovery.exe in "Program Files\Windows Home Server" does the trick and in 10 minutes I have all my clients connected. (See update from June 8). That's it.

P.S. I was also worried about licensing, but when I was prompted to active new WHS, I simply clicked on the balloon and successfully finished activation without any issues.

Updated on June 8, 2008: I was having issues with passwords on my clients - each time server or client machine was rebooted, a balloon was displayed with "Passwords do not match" message. To make sure passwords indeed match, I have completed Update Password wizard, but this didn't help. So I submitted a bug into Microsoft's connect site and received suggestion to uninstall and install again client's software. I have followed it on 2 computers and issue was solved. To conclude - do not use Discovery.exe to connect to new home server. Instead simply reinstall client connector software.

Technorati Tags: ,

Memory Limits in Windows systems

Well, I was thinking to add additional 4 Gigs or RAM into my Windows Home Server and wasn't sure it can handle it, since it is available only in 32 bit version. So after searching around, I found this link from MSDN explaining memory limits in various Windows systems:

http://msdn.microsoft.com/en-us/library/aa366778(VS.85).aspx

Short answer to my question - WHS (and Vista BTW) supports up to 4GB of RAM.

Technorati Tags: , , ,

MyHeritage.com Match-A-Celebrity!

Well, I'm using MyHeritage.com site to hold all my genealogy tree and recently they have added ability to check which celebrities you look like. Pretty nice feature :) Unfortunately I only had a picture of me with sunglasses at this computer, so results are not that accurate, but still fun - specially I like how I match Eddie Murphy and Liza Minelli :)

 

Technorati Tags: , ,

ADO.NET Entity Framework, SQLCE and identity columns

Recently I've doing some works using MS SQL Compact Edition and for data layer ADO.NET Entity Framework was chosen. Now MS only recently added support for SQLCE in the framework, so its kind of beta inside beta. Some features are not working properly or missing, as for example, support for identity columns. While SQLCE provides support for auto-generated columns, the framework doesn't yet have it. And of course all my IDs in tables are auto-generated integer values, e.g. identity.

Of course the only option was to generate ID at client. But I didn't want to change everything to be GUID, which looks like the only option at first glance, so I was looking for a way to generate integer values. I wouldn't even think about it if I was working with SQL Server, but at the end this is SQL CE, which is not supposed to (and would not in the scope of this project) be used by different processes, so I can synchronize identity generating in-process without problems.

The solution is not something genius and its simple, but its worked for me. The only downside that I saw is that I have to add partial class for every entity in my database. Well, since I had about 15 of them, this was not a big deal. The method is added to the class that extends ObjectContext, e.g. your model class:

private static Dictionary<Type, int> _primaryKeysCache = new Dictionary<Type, int>();
public static int GenerateID<TEntity>(
Func<Model, ObjectQuery<TEntity>> table,
Func<TEntity, int> idSelector) where TEntity : EntityObject
{
lock (_primaryKeysCache)
{
int primaryKey = 0;
if (!_primaryKeysCache.TryGetValue(typeof(TEntity), out primaryKey))
{
using (Model model = Model.CreateContext())
{
primaryKey = table(model).Any() ? table(model).Max(idSelector) : 0;
}
}
primaryKey++;
_primaryKeysCache[typeof(TEntity)] = primaryKey;
return primaryKey;
}
}

In this method, "Model" is my ObjectContext and the "Model.CreateContext()" is a simple static method that returns a new instance of objects model.

Usage of this method is simple - just call it when you want to generate a new ID value. Only warning - do not do this in object's constructor, you will get endless recursion. In the example below, I have a class that stores information about single file on disk. I always create a new class using the method "New()":

partial class GenericFile
{
public static GenericFile New()
{
GenericFile ret = new GenericFile();
if (Model.ShouldGenerateID)
ret.ID = Model.GenerateID(m => m.Files, f => f.ID);
return ret;
}
}

Another thing you might note here - the static property "ShouldGenerateID" on my model. I thought to myself that probably in the future, the issue will be solved and I will not need to generate IDs myself. So I have added this boolean that currently always returns true.

Updated: June 3, 2008: For general info on how to start with SQLCE and Entity Framework, see this post in SQLCE Devs' blog

Technorati Tags: , , , , ,