Join Webhostforasp.net
dailtcode logo

Self updating windows program

clock November 18, 2008 22:20 by author mderaeve

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)
{
        Assembly a = Assembly.LoadFile(@"M:\MRD\BRSSupport\BRSupport.exe");
        string newVersion = a.GetName().Version.ToString();
        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
 
 
 

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.

 



USB storage device not found

clock November 14, 2008 01:48 by author mderaeve

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.



My iGoogle theme on the Google theme's list

clock November 4, 2008 11:03 by author mderaeve

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!

 

 

 



Sharepoint workflow security error

clock October 17, 2008 00:26 by author mderaeve

Working with WSS, I use a lot of simple workflows that are created in SharePoint Designer. Quick and easy creation, deploying and maintaining in normal scenarios. BUT:

Suddenly on my development environment, the workflows where giving following error message: "You do not have permission to do this operation. Ask your Web site administrator to change your permissions and then try again, or log on with a user account that has this permission. To log on with a different user account click OK. " I really had to look hard for a solution. At first I tried everything I could to ensure the users I was using had sufficient rigths. It appeared it had nothing to do with the users I was using. These are the symptoms I was hving:

  • When I tried to save a workflow in SharePoint designer after I checked the options: Automatically start this workflow when item is created or changed I got this error: "You do not have permission to do this operation. Ask your Web site administrator to change your permissions and then try again, or log on with a user account that has this permission. To log on with a different user account click OK. "
  • When I tried to run a workflow manually I got an access denied error.

Googling didn't helped me a lot until I ended up here: http://kbalertz.com/947284/declarative-workflow-start-automatically-after-install-Windows-SharePoint-Services-Service.aspx

I set my application pool to run under the system account and then everything worked again. The reason why I started looking there was because on every web application on the server I had the same problems. It's strange that the sites kept on working but only the workflows had problems. After I changed the account for the application pool in the SharePoint administration website, I did a IISRESET /NOFORCE command.

Here's an article of Microsoft about this error: http://support.microsoft.com/kb/289335. The proposed solution could work in some cases, not in this case obviously!



Service not available, closing transmission channel. The server response was: 4.3.2 Service not available, closing transmission channel

clock October 15, 2008 22:20 by author mderaeve

Trying to look up this error only gave 2 results and did not provide the simple solution for this problem I found.

Thsi code worked fine before we changed to a secure Exchange 2007 server.

MailBody.Insert(0, "Dear, <br><br>");
 
            string[] mails = toString.Split(';');
  
            MailAddress from = new MailAddress(sharepoint@dailycode.net);
 
            MailMessage Message = new MailMessage();
 
            foreach (string mailAdress in mails)
            {
                Message.To.Add(mailAdress);
            }
            Message.From = from;
            Message.Subject = "Document needs revising!";
            Message.Body = MailBody.ToString();
            Message.IsBodyHtml = true;
             
            SmtpClient smtpClient = new SmtpClient();
            smtpClient.Host = System.Configuration.ConfigurationSettings.AppSettings["SmtpServer"];
            smtpClient.Send(Message);

 

Then we changed and I got the beautifull error message: "Service not available, closing transmission channel. The server response was: 4.3.2 Service not available, closing transmission channel". So what did the trick was adding:

            smtpClient.UseDefaultCredentials = true;


You can also pass credentials if the program will run under a local user.  This can be done like this:

      smtpClient.Credentials = GetMailCredentials();
 
private static System.Net.NetworkCredential GetMailCredentials()
        {
            System.Net.NetworkCredential cred = new System.Net.NetworkCredential();
            cred.UserName = ConfigurationSettings.AppSettings["User"];
            cred.Password = ConfigurationSettings.AppSettings["Pwd"];
            cred.Domain = ConfigurationSettings.AppSettings["Dom"];
            return cred;
        }

 

Reading this makes it seem very logic, secure server disables anonymous login.

 


Search


Categories





Locations of visitors to this page

About

Mark Deraeve

Blogroll

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

This site was created by Jetro Wils and Deraeve Mark powered by BlogEngine

© Copyright 2008

Sign in