目前,我有一个C#服务,运行许多.dll并且具有在启动时导入的模块/插件。我想创建一个更新系统,基本上停止服务,删除任何被告知要删除的文件(旧版本),从服务器下载新版本,并启动服务。我相信除了删除部分之外,我已将此编码正确,因为只要我没有覆盖任何内容,该文件就会下载。如果我试图覆盖某些东西,它将无法正常工作,这就是为什么我要尝试先删除它。但是,当我将File.Delete()发送到我想要做的路径时,它会给我
access to the path is denied
。这是我的代码:
new Thread(new ThreadStart(() =>
{
ServiceController controller = new ServiceController("client");
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped);
try
{
if (um.FilesUpdated != null)
{
foreach (FilesUpdated file in um.FilesUpdated)
{
if (file.OldFile != null)
{
File.Delete(Path.Combine(Utility.AssemblyDirectory, file.OldFile));
}
if (file.NewFile != null)
{
wc.DownloadFile(cs.UpdateUrl + "/updates/client/" + file.NewFile, Path.Combine(Utility.AssemblyDirectory, file.NewFile));
}
}
}
if (um.ModulesUpdated != null)
{
foreach (ModulesUpdated module in um.ModulesUpdated)
{
if (module.OldModule != null)
{
File.Delete(Path.Combine(cs.ModulePath, module.OldModule));
}
if (module.NewModule != null)
{
wc.DownloadFile(cs.UpdateUrl + "/updates/client/modules/" + module.NewModule, Path.Combine(cs.ModulePath, module.NewModule));
}
}
}
}
catch (Exception ex)
{
Logger.log(ex);
}
controller.Start();
})).Start();
我相信这是因为文件正在使用中,但我似乎无法卸载它们。我虽然停止服务会工作,但显然不是。我还检查了文件,它们不是只读的(但文件夹是,它位于Program Files中,但我似乎无法以编程方式或手动方式将其设置为只读)。该服务也以管理员身份运行(NT AUTHORITY \ SYSTEM)。我已经阅读了有关卸载AppDomain的信息,但AppDomain.Unload(AppDomain.CurrentDomain);
也返回了一个例外。
不太确定,即使这是MEF或我的程序没有正确权限的问题......我会认为这主要是因为该文件正在使用中。
答案 0 :(得分:0)
您将永远无法从已经运行的进程更新程序,您使用的每个dll都将被锁定。
正如你所说,你可以在什么都不做之前创建一个新的应用程序域,在该域内执行你的真实代码,当需要更新然后你可以卸载它,但即使这样你也无法更新服务的可执行文件。
执行此操作的方法是使用单独的应用程序或服务。
如果您使用应用程序进行更新,则不能从您的服务启动它,即使在创建桌面之前服务也会运行,因此您的更新程序可能会失败。使更新程序在会话启动时运行,并让它成为查询服务器以进行更新的程序。
否则,如果您希望从其他服务更新,那么您的主服务可以启动更新服务,更新程序可以停止主服务。使用服务具有即使没有桌面也可以运行的优势,在每个示例的服务器机器的情况下,机器运行几个月甚至没有用户会话,因此使用桌面应用程序进行更新将无效
答案 1 :(得分:0)
我认为您可以通过使用和更改Web应用程序Web.config
中的GUID密钥来卸载MEF插件。之后,应用程序域将自动重新启动。
例如:
<appSettings>
<add key="ForceReloadKey" value="[GUID]"/>
</appSettings>