3

我正在创建一个能够自我更新的软件应用程序。启动后,应用程序检查是否有可用的更新,下载这些文件(程序集),然后继续加载它们。

但是,问题是当应用程序由多个用户同时运行时。在终端服务器上运行时会发生这种情况。该应用程序无法替换那些旧文件,因为 Windows 将它们锁定。

有没有简单的方法来解决这个问题?这是一个遗留应用程序,我没有时间更改应用程序的大部分内容或更新机制。

4

4 回答 4

3

好吧,Windows确实允许您重命名各个文件,即使它们正在使用中。因此,您可以重命名为更新的文件,用新版本替换它们并重新启动应用程序。

我想如果不更改更新机制,您将无法解决此问题。

于 2012-06-08T08:06:32.583 回答
3

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.

于 2012-06-08T08:12:04.377 回答
1

一个简单的解决方案是使用Shadow Copying

简单的例子:

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...
    }
}

您可以创建一个可执行文件,将您的应用程序(您的可执行用户现在正在启动)加载到使用影子复制的新应用程序域中。CachePath必须是特定于用户的,例如用户临时目录。

这样,每个用户都将创建应用程序加载的所有程序集的副本。但是您必须自己清理复制的文件。

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

于 2012-06-08T08:09:13.207 回答
0

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.

于 2012-06-08T08:09:43.503 回答