我正在创建一个能够自我更新的软件应用程序。启动后,应用程序检查是否有可用的更新,下载这些文件(程序集),然后继续加载它们。
然而,问题是当应用程序同时由多个用户运行时。在终端服务器上运行时会发生这种情况。该应用程序无法替换这些旧文件,因为Windows会将它们锁定。
有没有一种简单的方法可以解决这个问题?这是一个遗留应用程序,我没有时间来更改应用程序的大部分内容或更新机制。
答案 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个文件。该进程应以预定义的名称格式下载文件(例如,使用下划线连接它)。在该过程完成下载第五个文件之后,该过程应该终止所有其他进程(或者最好只删除与下载的程序集相关的进程),然后用新的程序替换程序集。然后再次启动流程。