Пример #1
0
        /// <summary>
        /// Unloads a module.
        /// </summary>
        /// <param name="moduleData">The module.</param>
        private static void StopModule(ModuleData moduleData)
        {
            try
            {
                for (int i = moduleData.Tasks.Length - 1; i >= 0; i--)
                {
                    TaskManagerService.Logger.Log(string.Format("Stopping task '{0}'...", moduleData.Tasks[i].TaskName));
                    TaskSupervisor.RemoveTask(moduleData.Tasks[i]);
                }

                TaskManagerService.Logger.Log(string.Format("Unloading AppDomain '{0}'...", moduleData.Domain.FriendlyName));
                AppDomain.Unload(moduleData.Domain);

                TaskManagerService.Logger.Log("AppDomain successfully unloaded.");

                if (moduleData.ZipFile != null && moduleData.ZipDirectory != null)
                {
                    Directory.Delete(moduleData.ZipDirectory, true);
                }

                _moduleList.Remove(moduleData);
            }
            catch (Exception e)
            {
                TaskManagerService.Logger.Log(string.Format("Exception caught while shutting down module '{0}'", moduleData.DllFile), e);
                throw;
            }
        }
Пример #2
0
        /// <summary>
        /// Loads a module from a zip file.
        /// </summary>
        /// <param name="zipFile">The path to the zip file.</param>
        /// <param name="startImmediately">True if execution should be started immediately after configuring the module, false if module should be configured but not started.</param>
        private static void LoadZipAndConfigure(string zipFile, bool startImmediately)
        {
            string tempPath = null;

            int i = 0;

            while (Directory.Exists(tempPath = Path.Combine(Path.Combine(Path.GetTempPath(), "TaskManager"), Path.GetRandomFileName())))
            {
                i++;
                if (i == 10)
                {
                    throw new Exception("Failed to create a new temporary folder.");
                }
            }

            if (!tempPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                tempPath += Path.DirectorySeparatorChar;
            }

            string overridePath = Path.Combine(Path.GetDirectoryName(zipFile), Path.GetFileNameWithoutExtension(zipFile)) + Path.DirectorySeparatorChar;

            string loaderDll     = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TaskManager.Loader.dll");
            string tempLoaderDll = Path.Combine(tempPath, "TaskManager.Loader.dll");
            string commonDll     = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TaskManager.Common.dll");
            string tempCommonDll = Path.Combine(tempPath, "TaskManager.Common.dll");

            List <string> dependencies = new List <string>();

            DirectoryInfo directoryInfo = Directory.CreateDirectory(tempPath);

            try
            {
                using (Stream fileStream = File.Open(zipFile, FileMode.Open, FileAccess.Read))
                {
                    using (ZipArchive zip = new ZipArchive(fileStream, ZipArchiveMode.Read))
                    {
                        var directory = zip.Entries;

                        foreach (var compressedFile in directory)
                        {
                            string destinationFile = Path.Combine(tempPath, compressedFile.FullName);
                            string overrideFile    = Path.Combine(overridePath, compressedFile.FullName);
                            dependencies.Add(overrideFile);

                            compressedFile.ExtractToFile(destinationFile, true);
                        }
                    }
                }

                if (Directory.Exists(overridePath))
                {
                    foreach (string overrideFile in Directory.GetFiles(overridePath, "*.*", SearchOption.AllDirectories))
                    {
                        if (!dependencies.Contains(overrideFile))
                        {
                            dependencies.Add(overrideFile);
                        }

                        dependencies.Add(Path.Combine(overridePath, overrideFile.Replace(tempPath, string.Empty)));

                        string relativeName    = overrideFile.Replace(overridePath, string.Empty);
                        string destination     = Path.Combine(tempPath, relativeName);
                        string destinationPath = Path.GetDirectoryName(destination);

                        if (!Directory.Exists(destinationPath))
                        {
                            Directory.CreateDirectory(destinationPath);
                        }

                        File.Copy(overrideFile, destination, true);
                    }
                }

                List <string> possibleFiles = new List <string>();
                foreach (string moduleFile in Directory.GetFiles(tempPath, "*" + ModuleFileDefaultExtension, SearchOption.AllDirectories))
                {
                    string xmlFile = Path.ChangeExtension(moduleFile, ConfigFileDefaultExtension);

                    if (File.Exists(xmlFile))
                    {
                        possibleFiles.Add(moduleFile);
                    }
                }

                File.Copy(loaderDll, tempLoaderDll, true);
                File.Copy(commonDll, tempCommonDll, true);

                foreach (string dllFile in possibleFiles)
                {
                    string xmlFile = Path.ChangeExtension(dllFile, ConfigFileDefaultExtension);

                    if (File.Exists(xmlFile))
                    {
                        if (!xmlFile.IsValidConfigurationFile())
                        {
                            continue;
                        }

                        string modulePath = Path.GetDirectoryName(dllFile);

                        string[] files = Directory.GetFiles(modulePath, "*.*", SearchOption.AllDirectories);

                        AppDomainSetup domainSetup = new AppDomainSetup();
                        domainSetup.ShadowCopyFiles   = "true";
                        domainSetup.ApplicationBase   = tempPath;
                        domainSetup.ConfigurationFile = dllFile + ".config";

                        AppDomain domain = AppDomain.CreateDomain(dllFile, null, domainSetup);

                        TaskWrapper[] tasks = new TaskWrapper[0];

                        try
                        {
                            TaskManagerService.Logger.Log(string.Format("Module found: '{0}', configuration file: '{1}', scanning assembly for tasks...", dllFile, xmlFile));

                            AssemblyName loaderAssemblyName = AssemblyName.GetAssemblyName(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TaskManager.Loader.dll"));
                            Loader       loader             = (Loader)domain.CreateInstanceAndUnwrap(loaderAssemblyName.ToString(), "TaskManager.Loader");

                            tasks = loader.LoadAndConfigure(dllFile, xmlFile, TaskManagerService.Logger, AppDomain.CurrentDomain.BaseDirectory);

                            ModuleData newModule = new ModuleData();
                            newModule.BasePath     = overridePath;
                            newModule.Tasks        = tasks;
                            newModule.DllFile      = dllFile;
                            newModule.XmlFile      = xmlFile;
                            newModule.ZipFile      = zipFile;
                            newModule.ZipDirectory = tempPath;
                            newModule.Files        = new List <string>(files);
                            newModule.Files.AddRange(dependencies);
                            newModule.Files.Add(zipFile);
                            newModule.Domain = domain;

                            if (startImmediately)
                            {
                                foreach (TaskWrapper task in newModule.Tasks)
                                {
                                    TaskSupervisor.ScheduleTask(task);
                                }
                            }

                            _moduleList.Add(newModule);
                        }
                        catch (Exception ex)
                        {
                            foreach (TaskWrapper task in tasks)
                            {
                                try
                                {
                                    TaskSupervisor.RemoveTask(task);
                                }
                                catch
                                {
                                }
                            }

                            AppDomain.Unload(domain);

                            TaskManagerService.Logger.Log(string.Format("Unable to load module '{0}' from zipped file '{1}'.", dllFile, zipFile), ex);
                        }
                    }
                }

                foreach (ModuleData module in _moduleList)
                {
                    if (module.ZipFile == zipFile)
                    {
                        return;
                    }
                }

                throw new Exception(string.Format("Unable to find tasks in zipped file '{0}'.", zipFile));
            }
            catch
            {
                try
                {
                    Directory.Delete(tempPath, true);
                }
                catch (Exception ex)
                {
                    TaskManagerService.Logger.Log(string.Format("Unable to remove temporary directory '{0}'.", tempPath), ex);
                }

                throw;
            }
        }