运行时不要锁定应用程序的文件

时间:2012-06-08 08:01:16

标签: .net self-updating

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

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

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

4 个答案:

答案 0 :(得分:3)

大多数updater都有一个bootstrapper可执行文件,可以执行主应用程序的更新。

想法是运行引导程序而不是应用程序。然后,如果需要,引导程序会在启动实际应用程序之前应用任何更新。

另一种技术(我从未尝试过,它只是一个线索)是使用shadow assemblies。这个概念是“复制”文件上的程序集,以避免文件使用锁定。

最后,如果您接受此机制的缺点,可以查看clickonce,它可以轻松创建自我更新应用程序。

答案 1 :(得分:2)

嗯,Windows 允许您重命名相应的文件,即使它们正在使用中。因此,您可以重命名为更新的文件,将其替换为新版本并重新启动应用程序。

我想如果不改变更新机制,你将无法解决这个问题。

答案 2 :(得分: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必须是用户特定的,例如用户临时目录。

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

然后,您需要做的就是确保应用程序由新的包装器可执行文件启动。

答案 3 :(得分:0)

我猜您是直接下载程序集代替旧程序集。假设你有一个程序集myprogram.dll。首先下载具有不同名称的新更新的dll(例如_myprogram.dll)。在下载竞争之后触发事件,将用_myprogram.dll替换myprogram.dll。此事件应首先声明所有正在运行的进程停止然后替换程序集。更换应该在一瞬间。在这一刻你无法避免服务削减。

编辑:

应该有一个始终运行并检查更新的进程。首先将文件名发送到此进程。现在,该过程将下载例如5个文件。该进程应以预定义的名称格式下载文件(例如,使用下划线连接它)。在该过程完成下载第五个文件之后,该过程应该终止所有其他进程(或者最好只删除与下载的程序集相关的进程),然后用新的程序替换程序集。然后再次启动流程。