/// <summary> /// Main method for loading and parsing of the beta/installed folders. /// </summary> private void LoadAddinsOnStartup() { var addins = File.Exists(InstallDirectory + "BetaSettings.json") ? DeserializeSetting(InstallDirectory + "BetaSettings.json") : null; var dic = new Dictionary <string, AddinWrapper>(); // (Konrad) It's possible for user to be offline, and have no access to Beta HOK Drive. // In that case we still want to create addins, but instead use the Temp location on local drive. var betaTemp2 = Directory.Exists(BetaDirectory) ? BetaTempDirectory : Directory.Exists(TempDirectory) ? TempDirectory : string.Empty; if (betaTemp2 != string.Empty) { if (!Directory.Exists(TempDirectory)) { Directory.CreateDirectory(TempDirectory); } // (Konrad) Create a copy of all installed plugins by copying the temp dir from beta // We only do this if Beta is accessible otherwise we use local temp if (Directory.Exists(BetaDirectory)) { CopyAll(BetaTempDirectory, TempDirectory); } // (Konrad) We use the direcotry on the local drive that was already copied over to scan for addins. var availableAddins = Directory.GetFiles(betaTemp2, "*.addin"); // Cleans any holdovers from old beta addins RemoveLegacyPlugins(availableAddins); // (Konrad) Get all addins from beta directory foreach (var file in availableAddins) { var dllRelativePath = ParseXml(file); // relative to temp var dllPath = TempDirectory + dllRelativePath; if (!File.Exists(dllPath)) { continue; } // (Konrad) Using LoadFrom() instead of LoadFile() because // LoadFile() doesn't load dependent assemblies causing exception later. var assembly = Assembly.LoadFrom(dllPath); Type[] types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException e) { types = e.Types; } foreach (var t in types.Where(x => x != null && (x.GetInterface("IExternalCommand") != null || x.GetInterface("IExternalApplication") != null))) { MemberInfo info = t; var nameAttr = (NameAttribute)info.GetCustomAttributes(typeof(NameAttribute), true).FirstOrDefault(); var descAttr = (DescriptionAttribute)t.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault(); var imageAttr = (ImageAttribute)t.GetCustomAttributes(typeof(ImageAttribute), true).FirstOrDefault(); var namespaceAttr = (NamespaceAttribute)t.GetCustomAttributes(typeof(NamespaceAttribute), true).FirstOrDefault(); var panelNameAttr = (PanelNameAttribute)t.GetCustomAttributes(typeof(PanelNameAttribute), true).FirstOrDefault(); if (nameAttr == null || descAttr == null || imageAttr == null || namespaceAttr == null || panelNameAttr == null) { continue; } var bitmap = (BitmapSource)ButtonUtil.LoadBitmapImage(assembly, namespaceAttr.Namespace, imageAttr.ImageName); var version = assembly.GetName().Version.ToString(); var installed = false; var addin = addins?.FirstOrDefault(x => x.DllRelativePath == dllRelativePath); if (addin != null) { installed = addin.IsInstalled; if (installed) { // if directory doesn't exist in "installed" it means that it was not yet installed before. if (!Directory.Exists( InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name)) { Directory.CreateDirectory( InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name); CopyAll(betaTemp2 + new DirectoryInfo(addin.BetaResourcesPath).Name, InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name); } else { // directory exists, which means it was installed before // let's automatically copy the latest version in // we can use temp directory here since it was already either updated with latest // or is the only source of files (no network drive) CopyAll(TempDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name, InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name); } } } var aw = new AddinWrapper { Name = nameAttr.Name, Description = descAttr.Description, Image = bitmap, ImageName = imageAttr.ImageName, CommandNamespace = t.FullName, Version = version, IsInstalled = installed, InstalledVersion = version, BetaResourcesPath = Path.GetDirectoryName(dllPath), AddinFilePath = file, DllRelativePath = dllRelativePath, AutoUpdate = true, Panel = panelNameAttr.PanelName }; if (t.GetInterface("IExternalCommand") != null) { var buttonTextAttr = (ButtonTextAttribute)t.GetCustomAttributes(typeof(ButtonTextAttribute), true) .FirstOrDefault(); aw.ButtonText = buttonTextAttr?.ButtonText; } else { var additionalButtonNamesAttr = (AdditionalButtonNamesAttribute)t .GetCustomAttributes(typeof(AdditionalButtonNamesAttribute), true) .FirstOrDefault(); aw.AdditionalButtonNames = additionalButtonNamesAttr?.AdditionalNames; } dic.Add(aw.Name, aw); } } } var output = new ObservableCollection <AddinWrapper>(dic.Values.ToList().OrderBy(x => x.Name)); Addins = output; }
/// <summary> /// Retrieves all of the External Command addins created in this DLL. /// </summary> /// <returns></returns> public ObservableCollection <AddinWrapper> LoadAddins() { var output = new ObservableCollection <AddinWrapper>(); var dic = new Dictionary <string, AddinWrapper>(); // (Konrad) Retrieves information about External Commands currently in the loaded DLL. var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var name = Assembly.GetExecutingAssembly().GetName().Name + ".dll"; if (directory == null) { return(output); } var path = Path.Combine(directory, name); var asm = Assembly.LoadFrom(path); if (asm == null) { return(output); } var asmTypes = asm.GetTypes().Where(x => x.GetInterface("IExternalCommand") != null); foreach (var type in asmTypes) { var nameAttribute = type.GetCustomAttributes(typeof(NameAttribute), true) .FirstOrDefault() as NameAttribute; var descAttribute = type.GetCustomAttributes(typeof(DescriptionAttribute), true) .FirstOrDefault() as DescriptionAttribute; var imageAttribute = type.GetCustomAttributes(typeof(ImageAttribute), true) .FirstOrDefault() as ImageAttribute; var buttonTextAttribute = type.GetCustomAttributes(typeof(ButtonTextAttribute), true) .FirstOrDefault() as ButtonTextAttribute; var panelNameAttribute = type.GetCustomAttributes(typeof(PanelNameAttribute), true) .FirstOrDefault() as PanelNameAttribute; if (nameAttribute == null || descAttribute == null || imageAttribute == null || buttonTextAttribute == null || panelNameAttribute == null) { continue; } var aw = new AddinWrapper { Name = nameAttribute.Name, Description = descAttribute.Description, Image = imageAttribute.Image, ImageName = imageAttribute.ImageName, // (Konrad) Image name is assigned from Image attribute so order matters here. Panel = panelNameAttribute.PanelName, ButtonText = buttonTextAttribute.ButtonText, FullName = type.FullName }; dic.Add(aw.Name, aw); } // (Konrad) Deserializes previously stored information and updates the "Install" flag. var filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Properties.Resources.AddinManager_SettingsFileName; var storedAddins = File.Exists(filePath) ? Serialization.Deserialize(filePath) : null; if (storedAddins != null) { foreach (var addin in storedAddins) { if (dic.ContainsKey(addin.Name)) { dic[addin.Name].Install = addin.Install; } } } output = new ObservableCollection <AddinWrapper>(dic.Values.ToList().OrderBy(x => x.Name)); return(output); }