Dailycode.info

Short solution for short problems

My pride

The first non Computer related post is a fact.

This picture is just something that I want to share: Anna-Lisa (3 months old) and Priscilla (a little older)


Self updating windows program

(New post with improved funcionality can be found here.) 

 

In my company, we have a lot of separate tools for monitoring machines, flows, etc., for altering or viewing DB data, and you name it.


As lead .Net developer for my company, I decided to embed all windows applications in the same framework, making it easy to add functionality.   Every PC needed a simple installation and they could use all the functionalities. As the application grew, there was a need to embed security, because not all users have access  to all functionality. So I build in log-in and enhanced security, making it possible to hide each sub application according to the users role. But each time I made these changes to the program, I needed to update all the clients.

At first I was thinking of deploying via IIS (click-once), so we 1 central version, but this was not possible. The security was too tight. Using web-services or remoting could be a solution, but it was too slow. So a windows application was the best in this situation. 

The solution to all these problems was: creating a self updatable program. This challenge was tackled and solved. Not using application blocks, just a very simple solution. Here it is:   

The idea was to place the latest version on a drive map, and all programs would check before starting up if their version was up to date.   The biggest problem you encounter when writing an update procedure is that when you want to copy files, the program needs to be shutdown. You could write a wrapper that handles the update, but then, when the wrapper needs to be updated, you have the same problem. So I found another way. I guess many people have done it this way before, but I couldn't find it on Google.   At the start-up I have this code that calls the check version method:

Assembly asm = Assembly.GetExecutingAssembly();
//Check registration and version
CheckRegistration(asm.GetName().Version.ToString());
 
 

The checkregistration method handles the actual update, also writes the version to the database, so I can track the installed versions. 

       BU_BRSApps.Logic.BRSData data = new BU_BRSApps.Logic.BRSData();
       string compName = System.Windows.Forms.SystemInformation.ComputerName;
       if (!CheckVersion(currentVersion, ref string newVersion )){ 
DialogResult res = MessageBox.Show("Program needs to be updated, update now?", 
"Update",MessageBoxButtons.YesNo);
        if (res == DialogResult.Yes)
        {
MessageBox.Show("Program will restart automatically in a few seconds.");
               data.DeleteRegistration(compName);
               GeneralFunctions.ProcessBatchFile("updater.bat");
               data.InsertRegistration(compName, newVersion);
               this.Dispose(true);
               this.Close();
        }
}
 

The first methods you encounter is the CheckVersion method, this is to check the current version against the one on the file share. Here's the code for that: 

 
private bool CheckVersion(string currentVersion, ref string newVersion)
{
        BU_BRSApps.Logic.BRSData data = new BU_BRSApps.Logic.BRSData();
        newVersion = data.GetRegistration("LatestVersion");
        if (newVersion == currentVersion)
        {
               return true;
        }
        return false;
}
 
 
 

If the assemblies are different, it means that a new version is available on the file share and the current version needs to be updated. Now the trick on how to do the actual update:    

 MessageBox.Show("Program will restart automatically in a few seconds.");
data.DeleteRegistration(compName);
GeneralFunctions.ProcessBatchFile("updater.bat");
data.InsertRegistration(compName, currentVersion);
this.Dispose(true);
this.Close();
 
 
 
 

First I delete the current version in the database, then I open the updater.bat file in a new process. When this process is started I insert the new version and close the current application. The ProcessBatchFile method opens the updater.bat file, this bat file is copied to the output directory and looks like this:   

 
 
ping 127.0.0.1
copy M:\MRD\BRSSupport
BRSupport.exe
exit
 
 

The first thing the bat file does is ping to the local adress, so the program has time to close down. Then it starts to copy the new files and when this is finished, it opens the application again. This process only takes a few seconds. During this time the user has no interaction because I set the process to run in the background. But I warn the user of this before they choose to update. After some testing it appears to be working fine. I'm going to test it some more to see if the time the ping takes is long enough for the slowest systems on the network.  

I know there are better solutions, I also know this works for me. If you have suggestions or ways to self-update a program better, please post comments. One thing I thaught of was: instead of using the .bat, a seperate exe file that does the work. This way I could interact better with the user. But no time for this yet.   In my company, fast and good solutions are needed, this one I had to think of and develop in 1 or 2 days max.

Go to part 2 


USB storage device not found

Ever had this problem?

You plug in an USB memory stick and nothing happens. Windows does not ask you to install software or doesn't tell you that a new device is connected. Strange...

You might want to check the device manager, because in my case Windows try to give a drive name to the usb device that was already mapped. So it will not work properly.

Just assign a free drive letter to the USB memory stick and immediately a window will pop up showing it's contents.


Send mail from WSS (using spcontext)

Don't start with the System.Net.Mail namespace, because Sharepoint has a better way to do this:

using Microsoft.SharePoint.Utilities;

SPUtility.SendEmail(SPContext.Current.Web, false, false, EmailTO, 
"Document review request", message.ToString());
 

If you like to address a person in CC or BCC, you will notice that you will have to use headers in your email. I tried this but it didn't send the mails. After a while a noticed that you are required to pass the from email adress to via the header.

When you do this, the mails are sent. The syntax looks like this:

 

 
StringDictionary headers = new StringDictionary();
headers.Add("to", "yourmail@dailycode.net");
headers.Add("bcc", "mymail@dailycode.net");
headers.Add("from","sharepoint@dailycode.net"); 
headers.Add("subject", "Instruction on Document: 120_01.doc");
headers.Add("content-type", "text/html");
////Then just use the SendEmail method:
bool test = SPUtility.SendEmail(SPContext.Current.Web, headers, message.ToString());
 
 

My iGoogle theme on the Google theme's list

Today I found my iGoogle theme in the Google directory and noticed that 353 users are currently using it.

It's on page 142 of the 212 pages!!!

You can use this link to check it out: http://www.google.com/ig/directory?q=jotunheimen&type=themes&dpos=themes

If you like nature, then you can add this theme and expect regulary updates, with more pictures and even better layout!

You can enter search terms: Jotunheimen or "mark deraeve" and you will find this theme too.

I encourage everyone who's a iGoogle user and has some XML knowledge to try it out!