简体   繁体   中英

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. 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 . 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). I've read about unloading the AppDomain but 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.

You will never be able to update your program from your already running process, each dll you did use will be locked.

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. After that, application domain will be automatically restarted.

For example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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