简体   繁体   English

MEF C#服务-DLL更新

[英]MEF C# Service - DLL Updating

Currently, I have a C# service that runs off of many .dll's and has modules/plugins that it imports at startup. 目前,我有一个C#服务,该服务可以从许多.dll中运行,并具有在启动时导入的模块/插件。 I would like to create an update system that basically stops the service, deletes any files it is told to delete (old versions), downloads new versions from a server, and starts the service. 我想创建一个更新系统,该系统基本上停止该服务,删除被告知要删除的任何文件(旧版本),从服务器下载新版本,然后启动该服务。 I believe I have coded this right except for the delete part, because as long as I am not overwriting anything, the file will download. 我相信除了删除部分以外,我已经对此权限进行了编码,因为只要不覆盖任何内容,文件就会下载。 If I try to overwrite something, it won't work, which is why I am trying to delete it before hand. 如果我尝试覆盖某些内容,它将无法正常工作,这就是为什么我要尝试先删除它。 However, when I do File.Delete() to the path that I want to do, it gives me access to the path is denied . 但是,当我对要执行的路径执行File.Delete()时,它使我access to the path is denied Here is my code: 这是我的代码:

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();

I believe it is because the files are in use, but I can't seem to unload them. 我相信这是因为文件正在使用中,但是我似乎无法卸载它们。 I though stopping the service would work, but apparently not. 我虽然可以停止服务,但显然不能。 I have also checked the files and they are not read-only (but the folder is, which is located in Program Files, however I couldn't seem to get it to not be read-only programmatically or manually). 我还检查了文件,它们不是只读的(但文件夹位于程序文件中,但是我似乎无法通过编程或手动方式将其设置为只读)。 The service is also being run as an administrator (NT AUTHORITY\\SYSTEM). 该服务还以管理员身份(NT AUTHORITY \\ SYSTEM)运行。 I've read about unloading the AppDomain but AppDomain.Unload(AppDomain.CurrentDomain); 我已经读过关于卸载AppDomain的信息,但是AppDomain.Unload(AppDomain.CurrentDomain); returned an exception as well. 也返回一个异常。

Not too sure even if this is a problem with MEF or my program just not having the correct permissions...I would assume that it's mainly because the file is in use. 即使这不是MEF的问题,还是我的程序没有正确的权限,也不太确定...我认为这主要是因为文件正在使用中。

You will never be able to update your program from your already running process, each dll you did use will be locked. 您将永远无法从已经运行的进程中更新程序,您使用过的每个dll都将被锁定。

As you say, you can create a new app domain before doing nothing, execute your real code inside that domain and when update needs to be done then you can unload it, but even this way you will not be able to update the service's executable. 如您所说,您可以在不执行任何操作之前创建一个新的应用程序域,在该域​​中执行您的真实代码,并且当需要完成更新时可以将其卸载,但是即使这样,您也将无法更新该服务的可执行文件。

The way to do this is to use a separate application or service. 执行此操作的方法是使用单独的应用程序或服务。

If you use an application to update, then it must not be launched from your service, a service runs even before a Desktop is created, so your updater can fail. 如果使用应用程序进行更新,则不得从服务中启动该应用程序,因为服务甚至在创建桌面之前就已运行,因此更新程序可能会失败。 Make your updater to run when a session starts and let it be the one which queries the server for updates. 使您的更新程序在会话开始时运行,并使其成为向服务器查询更新的程序。

Else, if you prefer to update from another service then your main service can start the update service and the updater can stop main service. 否则,如果您希望从另一个服务进行更新,则您的主服务可以启动更新服务,而更新程序可以停止主服务。 Using a service has the advantage it can run even without Desktop, in the case of a server machine per example is very common the machine to be running for months without even having an user session, so using a Desktop app for updating will not be effective. 使用服务的优点是即使没有桌面也可以运行服务,对于每个示例来说,在服务器计算机上非常普遍,该计算机要运行数月甚至没有用户会话,因此使用桌面应用程序进行更新将无效。 。

I think that you're able to unload MEF plugins by using and changing a GUID key in Web.config for the web application. 我认为您可以通过使用和更改Web应用程序的Web.config中的GUID密钥来卸载MEF插件。 After that, application domain will be automatically restarted. 之后,应用程序域将自动重新启动。

For example: 例如:

<appSettings>
  <add key="ForceReloadKey" value="[GUID]"/>
</appSettings>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM