Pergunta

I am creating a software application that is able to update itself. After the start, the application checks if there are updates avaiable, download those files (assemblies), and then proceeds loading them.

However, the problem is when the application is run by multiple users at the same time. This happens when running on a terminal server. The application can't replace those old files, since windows keeps them locked.

Is there a simple way to solve this problem? It's a legacy application, and I don't have the time to alter big parts of the application or the update mechanic.

Foi útil?

Solução

A simple solution would be to use Shadow Copying.

Simple example:

class Program
{
    static void Main(string[] args)
    {
        var x = AppDomain.CreateDomain("TestAssembly", null, new AppDomainSetup() { 
                                                            ShadowCopyFiles = "true",
                                                            CachePath = @"c:\tmp", 
                                                            ApplicationName = "ShadowCopyTest"
                                                       });
        var a = x.Load("TestAssembly"); // Load Assembly and run...
    }
}

You could create an executable that would load your application (your executable users are starting right now) into a new Application Domain using Shadow Copying. CachePath has to be user specific, e.g. the users temp directory.

This way, each user would create a copy of all assemblies loaded by your application. But you have to take care of cleaning up the copied files yourself.

All you have to do then is to ensure the application gets started by your new wrapper executable.

Outras dicas

Well, Windows does allow you to rename the respective files even though they are in use. So you could rename to updated files, replace them with the new version and restart the application.

I guess you won't be able to solve this without changing the update mechanism.

Most of updater have a bootstrapper executable that performs the update of the main application.

The idea is to run the bootstrapper instead of your application. Then the bootstrapper apply any update if required, before launching the actual application.

Another technique (I never tried, it's only a clue) is to use shadow assemblies. The concept is to "duplicate" the assembly on the file in order to avoid file in use locking.

Finally, you can take a look at clickonce which can easily create self updating applications, if you accepts the drawbacks of this mechanism.

I guess you are downloading assemblies directly in place of the old assemblies. Lets say you have an assembly myprogram.dll . First download the new updated dll with a different name ( _myprogram.dll for example) . Fire an event after the download is competed that will replace the myprogram.dll with _myprogram.dll. This event should declare all running processes to stop at first then replace the assemblies. replacement should take at a moment. You cannot avoid the service cut on this moment.

EDİT:

There should be a process that will always running and checking for updates. Send the name of the files to this process first. The process will now it will download for example 5 files. The process should download the files in a predefined name format(Concatenating it with underscore for example). After the process finishes downloading 5th file the process should kill all other processes ( or preferably only the processes related to the downloaded assemblies), then replace the assemblies with the newer ones. Than start the processes again.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top