1

目前,我有一个 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 的问题或者我的程序没有正确的权限也不太确定......我认为这主要是因为该文件正在使用中。

4

2 回答 2

0

您将永远无法从已经运行的进程中更新您的程序,您使用的每个 dll 都将被锁定。

正如您所说,您可以在什么都不做之前创建一个新的应用程序域,在该域​​中执行您的真实代码,当需要更新时,您可以将其卸载,但即使这样您也无法更新服务的可执行文件。

这样做的方法是使用单独的应用程序或服务。

如果您使用应用程序进行更新,则不得从您的服务启动它,服务甚至在创建桌面之前运行,因此您的更新程序可能会失败。让您的更新程序在会话开始时运行,并让它成为查询服务器以获取更新的更新程序。

否则,如果您更喜欢从另一个服务更新,那么您的主服务可以启动更新服务,而更新程序可以停止主服务。使用服务的优点是即使没有桌面也可以运行,在服务器机器的例子中很常见,机器运行几个月甚至没有用户会话,所以使用桌面应用程序进行更新不会有效.

于 2014-06-12T03:21:06.573 回答
0

我认为您可以通过使用和更改Web.configWeb 应用程序的 GUID 键来卸载 MEF 插件。之后,应用程序域将自动重新启动。

例如:

<appSettings>
  <add key="ForceReloadKey" value="[GUID]"/>
</appSettings>
于 2019-05-15T13:52:32.273 回答