/// <summary> /// Unzips each .cplz archive into the temp directory and moves any unloaded files into loadedPlugins /// </summary> static void UnzipAndMoveCplzArchives() { Debug.Console(0, "Looking for .cplz archives from plugins folder..."); var di = new DirectoryInfo(_pluginDirectory); var zFiles = di.GetFiles("*.cplz"); if (zFiles.Length > 0) { if (!Directory.Exists(_loadedPluginsDirectoryPath)) { Directory.CreateDirectory(_loadedPluginsDirectoryPath); } } foreach (var zfi in zFiles) { Directory.CreateDirectory(_tempDirectory); var tempDi = new DirectoryInfo(_tempDirectory); Debug.Console(0, "Found cplz: {0}. Unzipping into temp plugins directory", zfi.Name); var result = CrestronZIP.Unzip(zfi.FullName, tempDi.FullName); Debug.Console(0, "UnZip Result: {0}", result.ToString()); var tempFiles = tempDi.GetFiles("*.dll"); foreach (var tempFile in tempFiles) { try { if (!CheckIfAssemblyLoaded(tempFile.Name)) { string filePath = string.Empty; filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + tempFile.Name; // Check if there is a previous file in the loadedPlugins directory and delete if (File.Exists(filePath)) { Debug.Console(0, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath); File.Delete(filePath); } // Move the file File.Move(tempFile.FullName, filePath); Debug.Console(2, "Moved {0} to {1}", tempFile.FullName, filePath); } else { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Skipping assembly: {0}. There is already an assembly with that name loaded.", tempFile.FullName); } } catch (Exception e) { Debug.Console(2, "Assembly {0} is not a custom assembly. Exception: {1}", tempFile.FullName, e); continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here } } // Delete the .cplz and the temp directory Directory.Delete(_tempDirectory, true); zfi.Delete(); } Debug.Console(0, "Done with .cplz archives"); }
/// <summary> /// Initial simple implementation. Reads user/programXX/plugins folder and /// use /// </summary> void LoadPlugins() { var dir = Global.FilePathPrefix + "plugins"; if (Directory.Exists(dir)) { // TODO Clear out or create localPlugins folder (maybe in program slot folder) Debug.Console(0, Debug.ErrorLogLevel.Notice, "Plugins directory found, checking for factory plugins"); var di = new DirectoryInfo(dir); var zFiles = di.GetFiles("*.cplz"); foreach (var fi in zFiles) { Debug.Console(0, "Found cplz: {0}. Unzipping into plugins directory", fi.Name); var result = CrestronZIP.Unzip(fi.FullName, di.FullName); Debug.Console(0, "UnZip Result: {0}", result.ToString()); fi.Delete(); } var files = di.GetFiles("*.dll"); Dictionary <string, Assembly> assyList = new Dictionary <string, Assembly>(); foreach (FileInfo fi in files) { // TODO COPY plugin to loadedPlugins folder // TODO LOAD that loadedPlugins dll file try { var assy = Assembly.LoadFrom(fi.FullName); var ver = assy.GetName().Version; var verStr = string.Format("{0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision); assyList.Add(fi.FullName, assy); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loaded plugin file '{0}', version {1}", fi.FullName, verStr); } catch { Debug.Console(2, "Assembly {0} is not a custom assembly", fi.FullName); continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here } } foreach (var assy in assyList) { // iteratate this assembly's classes, looking for "LoadPlugin()" methods try { var types = assy.Value.GetTypes(); foreach (var type in types) { try { var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static); var loadPlugin = methods.FirstOrDefault(m => m.Name.Equals("LoadPlugin")); if (loadPlugin != null) { Debug.Console(2, "LoadPlugin method found in {0}", type.Name); var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); var minimumVersion = fields.FirstOrDefault(p => p.Name.Equals("MinimumEssentialsFrameworkVersion")); if (minimumVersion != null) { Debug.Console(2, "MinimumEssentialsFrameworkVersion found"); var minimumVersionString = minimumVersion.GetValue(null) as string; if (!string.IsNullOrEmpty(minimumVersionString)) { var passed = Global.IsRunningMinimumVersionOrHigher(minimumVersionString); if (!passed) { Debug.Console(0, Debug.ErrorLogLevel.Error, "Plugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin", minimumVersionString); continue; } else { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Passed plugin passed dependency check (required version {0})", minimumVersionString); } } else { Debug.Console(0, Debug.ErrorLogLevel.Warning, "MinimumEssentialsFrameworkVersion found but not set. Loading plugin, but your mileage may vary."); } } else { Debug.Console(0, Debug.ErrorLogLevel.Warning, "MinimumEssentialsFrameworkVersion not found. Loading plugin, but your mileage may vary."); } Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding plugin: {0}", assy.Key); loadPlugin.Invoke(null, null); } } catch { Debug.Console(2, "Load Plugin not found. {0} is not a plugin assembly", assy.Value.FullName); continue; } } } catch { Debug.Console(2, "Assembly {0} is not a custom assembly. Types cannot be loaded.", assy.Value.FullName); continue; } } // plugin dll will be loaded. Any classes in plugin should have a static constructor // that registers that class with the Core.DeviceFactory } }