From 5f24922f549e3e5897d05e642e5a00b07b45cda1 Mon Sep 17 00:00:00 2001
From: ShrlAlgo <903524121@qq.com>
Date: Thu, 4 Sep 2025 09:53:20 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/.idea.AddInManager/.idea/.gitignore | 13 +
.idea/.idea.AddInManager/.idea/encodings.xml | 4 +
.../.idea.AddInManager/.idea/indexLayout.xml | 8 +
AddInManager.addin | 14 +
AddInManager.sln | 22 +
AddInManager/AIM.cs | 120 ++
AddInManager/AddInManager.csproj | 58 +
AddInManager/Addin.cs | 112 ++
AddInManager/AddinItem.cs | 146 ++
AddInManager/AddinItemComparer.cs | 10 +
AddInManager/AddinManager.cs | 320 +++++
AddInManager/AddinType.cs | 13 +
AddInManager/Addins.cs | 172 +++
AddInManager/AddinsApplication.cs | 64 +
AddInManager/AddinsCommand.cs | 69 +
AddInManager/App.cs | 121 ++
AddInManager/AssemLoader.cs | 275 ++++
AddInManager/CAddInManagerFaceless.cs | 19 +
AddInManager/CAddInManagerManual.cs | 40 +
AddInManager/CAddInManagerReadOnly.cs | 33 +
AddInManager/FailedToRunECDialog.cs | 16 +
AddInManager/FileUtils.cs | 239 ++++
AddInManager/FolderTooBigDialog.cs | 24 +
AddInManager/IAddinNode.cs | 11 +
AddInManager/IniFile.cs | 56 +
AddInManager/ManifestFile.cs | 392 +++++
AddInManager/Properties/Resources.Designer.cs | 137 ++
AddInManager/Properties/Resources.resx | 145 ++
AddInManager/Properties/Settings.Designer.cs | 38 +
AddInManager/Properties/Settings.settings | 9 +
AddInManager/RelayCommand.cs | 32 +
AddInManager/Resources/Develop_16.png | Bin 0 -> 331 bytes
AddInManager/Resources/Develop_32.png | Bin 0 -> 558 bytes
AddInManager/StaticUtil.cs | 29 +
AddInManager/VisibilityMode.cs | 19 +
AddInManager/Wpf/AssemblySelectorWindow.xaml | 107 ++
.../Wpf/AssemblySelectorWindow.xaml.cs | 81 ++
AddInManager/Wpf/LeftMarginMultiplier.cs | 37 +
AddInManager/Wpf/MainWindow.xaml | 414 ++++++
AddInManager/Wpf/MainWindow.xaml.cs | 1274 +++++++++++++++++
AddInManager/Wpf/Styles/ModernStyles.xaml | 862 +++++++++++
AddInManager/app.config | 15 +
42 files changed, 5570 insertions(+)
create mode 100644 .idea/.idea.AddInManager/.idea/.gitignore
create mode 100644 .idea/.idea.AddInManager/.idea/encodings.xml
create mode 100644 .idea/.idea.AddInManager/.idea/indexLayout.xml
create mode 100644 AddInManager.addin
create mode 100644 AddInManager.sln
create mode 100644 AddInManager/AIM.cs
create mode 100644 AddInManager/AddInManager.csproj
create mode 100644 AddInManager/Addin.cs
create mode 100644 AddInManager/AddinItem.cs
create mode 100644 AddInManager/AddinItemComparer.cs
create mode 100644 AddInManager/AddinManager.cs
create mode 100644 AddInManager/AddinType.cs
create mode 100644 AddInManager/Addins.cs
create mode 100644 AddInManager/AddinsApplication.cs
create mode 100644 AddInManager/AddinsCommand.cs
create mode 100644 AddInManager/App.cs
create mode 100644 AddInManager/AssemLoader.cs
create mode 100644 AddInManager/CAddInManagerFaceless.cs
create mode 100644 AddInManager/CAddInManagerManual.cs
create mode 100644 AddInManager/CAddInManagerReadOnly.cs
create mode 100644 AddInManager/FailedToRunECDialog.cs
create mode 100644 AddInManager/FileUtils.cs
create mode 100644 AddInManager/FolderTooBigDialog.cs
create mode 100644 AddInManager/IAddinNode.cs
create mode 100644 AddInManager/IniFile.cs
create mode 100644 AddInManager/ManifestFile.cs
create mode 100644 AddInManager/Properties/Resources.Designer.cs
create mode 100644 AddInManager/Properties/Resources.resx
create mode 100644 AddInManager/Properties/Settings.Designer.cs
create mode 100644 AddInManager/Properties/Settings.settings
create mode 100644 AddInManager/RelayCommand.cs
create mode 100644 AddInManager/Resources/Develop_16.png
create mode 100644 AddInManager/Resources/Develop_32.png
create mode 100644 AddInManager/StaticUtil.cs
create mode 100644 AddInManager/VisibilityMode.cs
create mode 100644 AddInManager/Wpf/AssemblySelectorWindow.xaml
create mode 100644 AddInManager/Wpf/AssemblySelectorWindow.xaml.cs
create mode 100644 AddInManager/Wpf/LeftMarginMultiplier.cs
create mode 100644 AddInManager/Wpf/MainWindow.xaml
create mode 100644 AddInManager/Wpf/MainWindow.xaml.cs
create mode 100644 AddInManager/Wpf/Styles/ModernStyles.xaml
create mode 100644 AddInManager/app.config
diff --git a/.idea/.idea.AddInManager/.idea/.gitignore b/.idea/.idea.AddInManager/.idea/.gitignore
new file mode 100644
index 0000000..9bb7aef
--- /dev/null
+++ b/.idea/.idea.AddInManager/.idea/.gitignore
@@ -0,0 +1,13 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# Rider 忽略的文件
+/.idea.AddInManager.iml
+/modules.xml
+/contentModel.xml
+/projectSettingsUpdater.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.AddInManager/.idea/encodings.xml b/.idea/.idea.AddInManager/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.AddInManager/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.AddInManager/.idea/indexLayout.xml b/.idea/.idea.AddInManager/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.AddInManager/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AddInManager.addin b/AddInManager.addin
new file mode 100644
index 0000000..d0664fe
--- /dev/null
+++ b/AddInManager.addin
@@ -0,0 +1,14 @@
+
+
+
+ AddInManager.dll
+ 插件开发工具
+ E8196B4E-AC4F-4B22-BF75-48F9A6039BDA
+ AddInManager.App
+ Add-In Manager
+ AlwaysVisible
+ Unknown
+ ADSK
+ Autodesk, www.autodesk.com
+
+
diff --git a/AddInManager.sln b/AddInManager.sln
new file mode 100644
index 0000000..e55e977
--- /dev/null
+++ b/AddInManager.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddInManager", "AddInManager\AddInManager.csproj", "{1A000607-4238-4AB2-9E73-A6937E061ABE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1A000607-4238-4AB2-9E73-A6937E061ABE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A000607-4238-4AB2-9E73-A6937E061ABE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A000607-4238-4AB2-9E73-A6937E061ABE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A000607-4238-4AB2-9E73-A6937E061ABE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/AddInManager/AIM.cs b/AddInManager/AIM.cs
new file mode 100644
index 0000000..9a200d1
--- /dev/null
+++ b/AddInManager/AIM.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Reflection;
+using System.Windows;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+
+namespace AddInManager
+{
+ public sealed class AIM
+ {
+ public Result ExecuteCommand(ExternalCommandData data, ref string message, ElementSet elements, bool faceless)
+ {
+ if (ActiveCmd != null && faceless)
+ {
+ return RunActiveCommand(data, ref message, elements);
+ }
+
+ var mainWindow = new Wpf.MainWindow(this);
+ var dialogResult = mainWindow.ShowDialog();
+
+ if (dialogResult != true)
+ {
+ return Result.Cancelled;
+ }
+
+ // 窗口关闭后,检查是否有选中的命令需要执行
+ if (ActiveCmd != null && ActiveCmdItem != null)
+ {
+ return RunActiveCommand(data, ref message, elements);
+ }
+
+ return Result.Succeeded; // 如果没有命令要执行,返回成功
+ }
+
+ public string ActiveTempFolder { get; set; } = string.Empty;
+
+ private Result RunActiveCommand(ExternalCommandData data, ref string message, ElementSet elements)
+ {
+ var filePath = ActiveCmd.FilePath;
+ var assemLoader = new AssemLoader();
+ Result result;
+ try
+ {
+ assemLoader.HookAssemblyResolve();
+ var assembly = assemLoader.LoadAddinsToTempFolder(filePath, false);
+ if (null == assembly)
+ {
+ result = Result.Failed;
+ }
+ else
+ {
+ ActiveTempFolder = assemLoader.TempFolder;
+ var externalCommand = assembly.CreateInstance(ActiveCmdItem.FullClassName) as IExternalCommand;
+ if (externalCommand == null)
+ {
+ result = Result.Failed;
+ }
+ else
+ {
+ ActiveEC = externalCommand;
+ result = ActiveEC.Execute(data, ref message, elements);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.ToString());
+ result = Result.Failed;
+ }
+ finally
+ {
+ assemLoader.UnhookAssemblyResolve();
+ assemLoader.CopyGeneratedFilesBack();
+ }
+ return result;
+ }
+
+ public static AIM Instance
+ {
+ get
+ {
+ if (m_inst == null)
+ {
+ lock (typeof(AIM))
+ {
+ if (m_inst == null)
+ {
+ m_inst = new AIM();
+ }
+ }
+ }
+ return m_inst;
+ }
+ }
+
+ private AIM()
+ {
+ AddinManager = new AddinManager();
+ ActiveCmd = null;
+ ActiveCmdItem = null;
+ ActiveApp = null;
+ ActiveAppItem = null;
+ }
+
+ public IExternalCommand ActiveEC { get; set; }
+
+ public Addin ActiveCmd { get; set; }
+
+ public AddinItem ActiveCmdItem { get; set; }
+
+ public Addin ActiveApp { get; set; }
+
+ public AddinItem ActiveAppItem { get; set; }
+
+ public AddinManager AddinManager { get; set; }
+
+ private static volatile AIM m_inst;
+ }
+}
diff --git a/AddInManager/AddInManager.csproj b/AddInManager/AddInManager.csproj
new file mode 100644
index 0000000..65eca3a
--- /dev/null
+++ b/AddInManager/AddInManager.csproj
@@ -0,0 +1,58 @@
+
+
+ Library
+ AddInManager
+ AddInManager
+ False
+ preview
+ True
+ False
+ False
+ net48
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
\ No newline at end of file
diff --git a/AddInManager/Addin.cs b/AddInManager/Addin.cs
new file mode 100644
index 0000000..b50b3df
--- /dev/null
+++ b/AddInManager/Addin.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace AddInManager
+{
+ public class Addin : IAddinNode
+ {
+ public List ItemList { get; set; }
+
+ public string FilePath { get; set; }
+
+ public bool Save { get; set; }
+
+ public bool Hidden { get; set; }
+
+ public Addin(string filePath)
+ {
+ ItemList = new List();
+ FilePath = filePath;
+ Save = true;
+ }
+
+ public Addin(string filePath, List itemList)
+ {
+ ItemList = itemList;
+ FilePath = filePath;
+ SortAddinItem();
+ Save = true;
+ }
+
+ public void SortAddinItem()
+ {
+ ItemList.Sort(new AddinItemComparer());
+ }
+
+ public void RemoveItem(AddinItem item)
+ {
+ ItemList.Remove(item);
+ if (ItemList.Count == 0)
+ {
+ AIM.Instance.AddinManager.RemoveAddin(this);
+ }
+ }
+
+ public void SaveToLocalIni(IniFile file)
+ {
+ if (ItemList == null || ItemList.Count == 0)
+ {
+ return;
+ }
+ var addinType = ItemList[0].AddinType;
+ if (addinType == AddinType.Command)
+ {
+ file.WriteSection("ExternalCommands");
+ file.Write("ExternalCommands", "ECCount", 0);
+ var num = 0;
+ foreach (var addinItem in ItemList)
+ {
+ if (addinItem.Save)
+ {
+ WriteExternalCommand(file, addinItem, ++num);
+ }
+ }
+ file.Write("ExternalCommands", "ECCount", num);
+ return;
+ }
+ file.WriteSection("ExternalApplications");
+ file.Write("ExternalApplications", "EACount", 0);
+ var num2 = 0;
+ foreach (var addinItem2 in ItemList)
+ {
+ WriteExternalApplication(file, addinItem2, ++num2);
+ }
+ file.Write("ExternalApplications", "EACount", num2);
+ }
+
+ private void WriteExternalCommand(IniFile file, AddinItem item, int number)
+ {
+ file.Write("ExternalCommands", $"ECName{number}", item.Name);
+ file.Write("ExternalCommands", $"ECClassName{number}", item.FullClassName);
+ file.Write("ExternalCommands", $"ECAssembly{number}", item.AssemblyName);
+ file.Write("ExternalCommands", $"ECDescription{number}", item.Description);
+ }
+
+ private void WriteExternalApplication(IniFile file, AddinItem item, int number)
+ {
+ file.Write("ExternalApplications", $"EAClassName{number}", item.FullClassName);
+ file.Write("ExternalApplications", $"EAAssembly{number}", item.AssemblyName);
+ }
+
+ public void SaveToLocalManifest()
+ {
+ if (ItemList == null || ItemList.Count == 0)
+ {
+ return;
+ }
+ var addinType = ItemList[0].AddinType;
+ var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(FilePath);
+ var manifestFile = new ManifestFile($"{fileNameWithoutExtension}.addin");
+ if (addinType == AddinType.Application)
+ {
+ manifestFile.Applications = ItemList;
+ }
+ else if (addinType == AddinType.Command)
+ {
+ manifestFile.Commands = ItemList;
+ }
+ manifestFile.Save();
+ }
+ }
+}
diff --git a/AddInManager/AddinItem.cs b/AddInManager/AddinItem.cs
new file mode 100644
index 0000000..f4d324b
--- /dev/null
+++ b/AddInManager/AddinItem.cs
@@ -0,0 +1,146 @@
+using System;
+using System.IO;
+
+using Autodesk.Revit.Attributes;
+
+namespace AddInManager
+{
+ public class AddinItem : IAddinNode
+ {
+ public AddinItem(AddinType type)
+ {
+ AddinType = type;
+ m_clientId = Guid.NewGuid();
+ ClientIdString = m_clientId.ToString();
+ m_assemblyPath = string.Empty;
+ AssemblyName = string.Empty;
+ FullClassName = string.Empty;
+ m_name = string.Empty;
+ Save = true;
+ VisibilityMode = VisibilityMode.AlwaysVisible;
+ }
+
+ public AddinItem(string assemblyPath, Guid clientId, string fullClassName, AddinType type, TransactionMode? transactionMode, RegenerationOption? regenerationOption, JournalingMode? journalingMode)
+ {
+ TransactionMode = transactionMode;
+ RegenerationMode = regenerationOption;
+ JournalingMode = journalingMode;
+ AddinType = type;
+ m_assemblyPath = assemblyPath;
+ AssemblyName = Path.GetFileName(m_assemblyPath);
+ m_clientId = clientId;
+ ClientIdString = clientId.ToString();
+ FullClassName = fullClassName;
+ var num = fullClassName.LastIndexOf(".");
+ m_name = fullClassName.Substring(num + 1);
+ Save = true;
+ VisibilityMode = VisibilityMode.AlwaysVisible;
+ }
+
+ public void SaveToManifest()
+ {
+ var manifestFile = new ManifestFile($"{m_name}.addin");
+ if (AddinType == AddinType.Application)
+ {
+ manifestFile.Applications.Add(this);
+ }
+ else if (AddinType == AddinType.Command)
+ {
+ manifestFile.Commands.Add(this);
+ }
+ manifestFile.Save();
+ }
+
+ public AddinType AddinType { get; set; }
+
+ public string AssemblyPath
+ {
+ get => m_assemblyPath;
+ set
+ {
+ m_assemblyPath = value;
+ AssemblyName = Path.GetFileName(m_assemblyPath);
+ }
+ }
+
+ public string AssemblyName { get; set; }
+
+ public Guid ClientId
+ {
+ get => m_clientId;
+ set
+ {
+ m_clientId = value;
+ ClientIdString = m_clientId.ToString();
+ }
+ }
+
+ protected internal string ClientIdString { get; set; }
+
+ public string FullClassName { get; set; }
+
+ public string Name
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(m_name))
+ {
+ return "External Tool";
+ }
+ return m_name;
+ }
+ set
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ m_name = value;
+ return;
+ }
+ m_name = "External Tool";
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(m_description))
+ {
+ return "\"\"";
+ }
+ return m_description;
+ }
+ set
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ m_description = "\"\"";
+ return;
+ }
+ m_description = value;
+ }
+ }
+
+ public VisibilityMode VisibilityMode { get; set; }
+
+ public bool Save { get; set; }
+
+ public bool Hidden { get; set; }
+
+ public TransactionMode? TransactionMode { get; set; }
+
+ public RegenerationOption? RegenerationMode { get; set; }
+
+ public JournalingMode? JournalingMode { get; set; }
+
+ public override string ToString()
+ {
+ return m_name;
+ }
+
+ protected string m_assemblyPath;
+ protected Guid m_clientId;
+ private string m_name;
+ private string m_description;
+ }
+}
diff --git a/AddInManager/AddinItemComparer.cs b/AddInManager/AddinItemComparer.cs
new file mode 100644
index 0000000..db5b6f3
--- /dev/null
+++ b/AddInManager/AddinItemComparer.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+
+namespace AddInManager
+{
+ public class AddinItemComparer : IComparer
+ {
+ public int Compare(AddinItem x, AddinItem y) => string.Compare(x?.Name, y?.Name, StringComparison.Ordinal);
+ }
+}
diff --git a/AddInManager/AddinManager.cs b/AddInManager/AddinManager.cs
new file mode 100644
index 0000000..c528f29
--- /dev/null
+++ b/AddInManager/AddinManager.cs
@@ -0,0 +1,320 @@
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+
+using AddInManager.Properties;
+
+namespace AddInManager
+{
+ public class AddinManager
+ {
+ public AddinsApplication Applications { get; }
+
+ public int AppCount => Applications.Count;
+
+ public AddinsCommand Commands { get; }
+
+ public int CmdCount => Commands.Count;
+
+ public AddinManager()
+ {
+ Commands = new AddinsCommand();
+ Applications = new AddinsApplication();
+ GetIniFilePaths();
+ ReadAddinsFromAimIni();
+ }
+
+ public IniFile AimIniFile { get; set; }
+
+ public IniFile RevitIniFile { get; set; }
+
+ private void GetIniFilePaths()
+ {
+ var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ var text = Path.Combine(folderPath, Settings.Default.AppFolder);
+ var text2 = Path.Combine(text, "AimInternal.ini");
+ AimIniFile = new IniFile(text2);
+ var currentProcess = Process.GetCurrentProcess();
+ var fileName = currentProcess.MainModule.FileName;
+ var text3 = fileName.Replace(".exe", ".ini");
+ RevitIniFile = new IniFile(text3);
+ }
+
+ public void ReadAddinsFromAimIni()
+ {
+ Commands.ReadItems(AimIniFile);
+ Applications.ReadItems(AimIniFile);
+ }
+
+ public void RemoveAddin(Addin addin)
+ {
+ if (!Commands.RemoveAddIn(addin))
+ {
+ Applications.RemoveAddIn(addin);
+ }
+ }
+
+ public AddinType LoadAddin(string filePath)
+ {
+ var addinType = AddinType.Invalid;
+ if (!File.Exists(filePath))
+ {
+ return addinType;
+ }
+ Path.GetFileName(filePath);
+ var assemLoader = new AssemLoader();
+ List list = null;
+ List list2 = null;
+ try
+ {
+ assemLoader.HookAssemblyResolve();
+ var assembly = assemLoader.LoadAddinsToTempFolder(filePath, true);
+ if (null == assembly)
+ {
+ return addinType;
+ }
+ list = Commands.LoadItems(assembly, StaticUtil.m_ecFullName, filePath, AddinType.Command);
+ list2 = Applications.LoadItems(assembly, StaticUtil.m_eaFullName, filePath, AddinType.Application);
+ }
+ catch (Exception)
+ {
+ }
+ finally
+ {
+ assemLoader.UnhookAssemblyResolve();
+ }
+ if (list != null && list.Count > 0)
+ {
+ var addin = new Addin(filePath, list);
+ Commands.AddAddIn(addin);
+ addinType |= AddinType.Command;
+ }
+ if (list2 != null && list2.Count > 0)
+ {
+ var addin2 = new Addin(filePath, list2);
+ Applications.AddAddIn(addin2);
+ addinType |= AddinType.Application;
+ }
+ return addinType;
+ }
+
+ public void SaveToRevitIni()
+ {
+ if (!File.Exists(RevitIniFile.FilePath))
+ {
+ throw new System.IO.FileNotFoundException(
+ $"can't find the revit.ini file from: {RevitIniFile.FilePath}",
+ RevitIniFile.FilePath
+);
+ }
+ Commands.Save(RevitIniFile);
+ Applications.Save(RevitIniFile);
+ }
+
+ public void SaveToLocal()
+ {
+ SaveToLocalManifest();
+ }
+
+ public void SaveToLocalRevitIni()
+ {
+ foreach (var keyValuePair in Commands.AddinDict)
+ {
+ var key = keyValuePair.Key;
+ var value = keyValuePair.Value;
+ var directoryName = Path.GetDirectoryName(value.FilePath);
+ var iniFile = new IniFile(Path.Combine(directoryName, "revit.ini"));
+ value.SaveToLocalIni(iniFile);
+ if (Applications.AddinDict.ContainsKey(key))
+ {
+ var addin = Applications.AddinDict[key];
+ addin.SaveToLocalIni(iniFile);
+ }
+ }
+ }
+
+ public void SaveToAimIni()
+ {
+ if (!File.Exists(AimIniFile.FilePath))
+ {
+ new FileInfo(AimIniFile.FilePath).Create();
+ FileUtils.SetWriteable(AimIniFile.FilePath);
+ }
+ Commands.Save(AimIniFile);
+ Applications.Save(AimIniFile);
+ }
+
+ public bool HasItemsToSave()
+ {
+ foreach (var addin in Commands.AddinDict.Values)
+ {
+ if (addin.Save)
+ {
+ return true;
+ }
+ }
+ foreach (var addin2 in Applications.AddinDict.Values)
+ {
+ if (addin2.Save)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public string SaveToAllUserManifest()
+ {
+ var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
+ var currentAddinFolder = Path.Combine(folderPath, $"Autodesk\\Revit\\Addins\\{App.RevitVersion}");
+ var manifestFile = new ManifestFile(false);
+ var numCmdAddins = 0;
+ Addin savedCmdAddin = null;
+ foreach (var cmdAddin in Commands.AddinDict.Values)
+ {
+ if (cmdAddin.Save)
+ {
+ numCmdAddins++;
+ savedCmdAddin = cmdAddin;
+ }
+ foreach (var addinItem in cmdAddin.ItemList)
+ {
+ if (addinItem.Save)
+ {
+ manifestFile.Commands.Add(addinItem);
+ }
+ }
+ }
+ var numAppAddins = 0;
+ Addin savedAppAddin = null;
+ foreach (var appAddin in Applications.AddinDict.Values)
+ {
+ if (appAddin.Save)
+ {
+ numCmdAddins++;
+ savedAppAddin = appAddin;
+ }
+ foreach (var appAddinItem in appAddin.ItemList)
+ {
+ if (appAddinItem.Save)
+ {
+ manifestFile.Applications.Add(appAddinItem);
+ numAppAddins++;
+ savedAppAddin = appAddin;
+ }
+ }
+ }
+ var addinFileName = string.Empty;
+ string addinFilePath;
+ if (numCmdAddins <= 1 && numAppAddins <= 1 && numCmdAddins + numAppAddins > 0)
+ {
+ if (savedCmdAddin != null)
+ {
+ if (savedAppAddin == null || savedCmdAddin.FilePath.Equals(savedAppAddin.FilePath, StringComparison.OrdinalIgnoreCase))
+ {
+ addinFileName = Path.GetFileNameWithoutExtension(savedCmdAddin.FilePath);
+ }
+ }
+ else if (savedAppAddin != null && savedCmdAddin == null)
+ {
+ addinFileName = Path.GetFileNameWithoutExtension(savedAppAddin.FilePath);
+ }
+ if (string.IsNullOrEmpty(addinFileName))
+ {
+ return string.Empty;
+ }
+ addinFilePath = GetProperFilePath(currentAddinFolder, addinFileName, ".addin");
+ }
+ else
+ {
+ addinFilePath = GetProperFilePath(currentAddinFolder, "ExternalTool", ".addin");
+ }
+ manifestFile.SaveAs(addinFilePath);
+ return addinFilePath;
+ }
+
+ public void SaveToLocalManifest()
+ {
+ var dictionary = new Dictionary();
+ var dictionary2 = new Dictionary();
+ foreach (var cmdKeyValuePair in Commands.AddinDict)
+ {
+ var key = cmdKeyValuePair.Key;
+ var value = cmdKeyValuePair.Value;
+ var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(value.FilePath);
+ var directoryName = Path.GetDirectoryName(value.FilePath);
+ var text = Path.Combine(directoryName, $"{fileNameWithoutExtension}.addin");
+ var manifestFile = new ManifestFile(true);
+ foreach (var addinItem in value.ItemList)
+ {
+ if (addinItem.Save)
+ {
+ manifestFile.Commands.Add(addinItem);
+ }
+ }
+ if (Applications.AddinDict.ContainsKey(key))
+ {
+ var addin = Applications.AddinDict[key];
+ foreach (var addinItem2 in addin.ItemList)
+ {
+ if (addinItem2.Save)
+ {
+ manifestFile.Applications.Add(addinItem2);
+ }
+ }
+ dictionary.Add(key, Applications.AddinDict[key]);
+ }
+ manifestFile.SaveAs(text);
+ }
+ foreach (var appKeyValuePair in Applications.AddinDict)
+ {
+ var key2 = appKeyValuePair.Key;
+ var value2 = appKeyValuePair.Value;
+ if (!dictionary.ContainsKey(key2))
+ {
+ var fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(value2.FilePath);
+ var directoryName2 = Path.GetDirectoryName(value2.FilePath);
+ var text2 = Path.Combine(directoryName2, $"{fileNameWithoutExtension2}.addin");
+ var manifestFile2 = new ManifestFile(true);
+ foreach (var addinItem3 in value2.ItemList)
+ {
+ if (addinItem3.Save)
+ {
+ manifestFile2.Applications.Add(addinItem3);
+ }
+ }
+ if (Commands.AddinDict.ContainsKey(key2))
+ {
+ var addin2 = Commands.AddinDict[key2];
+ foreach (var addinItem4 in addin2.ItemList)
+ {
+ if (addinItem4.Save)
+ {
+ manifestFile2.Commands.Add(addinItem4);
+ }
+ }
+ dictionary2.Add(key2, Commands.AddinDict[key2]);
+ }
+ manifestFile2.SaveAs(text2);
+ }
+ }
+ }
+
+ private static string GetProperFilePath(string folder, string fileNameWithoutExt, string ext)
+ {
+ var filePath = string.Empty;
+ var fileIndex = -1;
+ do
+ {
+ fileIndex++;
+ var text2 = ((fileIndex <= 0) ? (fileNameWithoutExt + ext) : (fileNameWithoutExt + fileIndex + ext));
+ filePath = Path.Combine(folder, text2);
+ }
+ while (File.Exists(filePath));
+ return filePath;
+ }
+ }
+}
diff --git a/AddInManager/AddinType.cs b/AddInManager/AddinType.cs
new file mode 100644
index 0000000..1357581
--- /dev/null
+++ b/AddInManager/AddinType.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace AddInManager
+{
+ [Flags]
+ public enum AddinType
+ {
+ Invalid = 0,
+ Command = 1,
+ Application = 2,
+ Mixed = 3
+ }
+}
diff --git a/AddInManager/Addins.cs b/AddInManager/Addins.cs
new file mode 100644
index 0000000..248a2eb
--- /dev/null
+++ b/AddInManager/Addins.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+using Autodesk.Revit.Attributes;
+
+namespace AddInManager
+{
+ public abstract class Addins
+ {
+ public SortedDictionary AddinDict
+ {
+ get => m_addinDict;
+ set => m_addinDict = value;
+ }
+
+ public int Count => m_addinDict.Count;
+
+ public Addins()
+ {
+ m_addinDict = new SortedDictionary();
+ }
+
+ public void SortAddin()
+ {
+ foreach (var addin in m_addinDict.Values)
+ {
+ addin.SortAddinItem();
+ }
+ }
+
+ public void AddAddIn(Addin addin)
+ {
+ var fileName = Path.GetFileName(addin.FilePath);
+ if (m_addinDict.ContainsKey(fileName))
+ {
+ m_addinDict.Remove(fileName);
+ }
+ m_addinDict[fileName] = addin;
+ }
+
+ public bool RemoveAddIn(Addin addin)
+ {
+ var fileName = Path.GetFileName(addin.FilePath);
+ if (m_addinDict.ContainsKey(fileName))
+ {
+ m_addinDict.Remove(fileName);
+ return true;
+ }
+ return false;
+ }
+
+ public void AddItem(AddinItem item)
+ {
+ var assemblyName = item.AssemblyName;
+ if (!m_addinDict.ContainsKey(assemblyName))
+ {
+ m_addinDict[assemblyName] = new Addin(item.AssemblyPath);
+ }
+ m_addinDict[assemblyName].ItemList.Add(item);
+ }
+
+ public List LoadItems(Assembly assembly, string fullName, string originalAssemblyFilePath, AddinType type)
+ {
+ var list = new List();
+ Type[] array = null;
+ try
+ {
+ array = assembly.GetTypes();
+ }
+ catch (ReflectionTypeLoadException ex)
+ {
+ array = ex.Types;
+ if (array == null)
+ {
+ return list;
+ }
+ }
+ var list2 = new List();
+ var list3 = new List();
+ foreach (var type2 in array)
+ {
+ try
+ {
+ if (!(null == type2) && !type2.IsAbstract)
+ {
+ var @interface = type2.GetInterface(fullName);
+ if (null != @interface)
+ {
+ TransactionMode? transactionMode = null;
+ RegenerationOption? regenerationOption = null;
+ JournalingMode? journalingMode = null;
+ if (type != AddinType.Application)
+ {
+ var customAttributes = Attribute.GetCustomAttributes(type2, false);
+ foreach (var attribute in customAttributes)
+ {
+ if (attribute is RegenerationAttribute)
+ {
+ var regenerationAttribute = (RegenerationAttribute)attribute;
+ regenerationOption = new RegenerationOption?(regenerationAttribute.Option);
+ }
+ if (attribute is TransactionAttribute)
+ {
+ var transactionAttribute = (TransactionAttribute)attribute;
+ transactionMode = new TransactionMode?(transactionAttribute.Mode);
+ }
+ if (attribute is JournalingAttribute)
+ {
+ var journalingAttribute = (JournalingAttribute)attribute;
+ journalingMode = new JournalingMode?(journalingAttribute.Mode);
+ }
+ if (transactionMode != null && regenerationOption != null)
+ {
+ break;
+ }
+ }
+ if (transactionMode == null)
+ {
+ list2.Add(type2.Name);
+ continue;
+ }
+ var mode = StaticUtil.m_tsactMode;
+ if (transactionMode != StaticUtil.m_tsactMode)
+ {
+ list3.Add(type2.Name);
+ continue;
+ }
+ }
+ var addinItem = new AddinItem(originalAssemblyFilePath, Guid.NewGuid(), type2.FullName, type, transactionMode, regenerationOption, journalingMode);
+ list.Add(addinItem);
+ }
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+ if (list2.Count > 0)
+ {
+ var stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine("The following Classes: ");
+ foreach (var text in list2)
+ {
+ stringBuilder.AppendLine(text);
+ }
+ stringBuilder.Append("implements IExternalCommand but doesn't contain both RegenerationAttribute and TransactionAttribute!");
+ StaticUtil.ShowWarning(stringBuilder.ToString());
+ }
+ if (list3.Count > 0)
+ {
+ var stringBuilder2 = new StringBuilder();
+ stringBuilder2.AppendLine("The TransactionMode set to Classes: ");
+ foreach (var text2 in list3)
+ {
+ stringBuilder2.AppendLine(text2);
+ }
+ stringBuilder2.Append(" are not the same as the mode set to Add-In Manager!");
+ StaticUtil.ShowWarning(stringBuilder2.ToString());
+ }
+ return list;
+ }
+
+ protected SortedDictionary m_addinDict;
+
+ protected int m_maxCount = 100;
+
+ protected int m_count;
+ }
+}
diff --git a/AddInManager/AddinsApplication.cs b/AddInManager/AddinsApplication.cs
new file mode 100644
index 0000000..cf31e0d
--- /dev/null
+++ b/AddInManager/AddinsApplication.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace AddInManager
+{
+ public class AddinsApplication : Addins
+ {
+ public void ReadItems(IniFile file)
+ {
+ var num = file.ReadInt("ExternalApplications", "EACount");
+ var i = 1;
+ while (i <= num)
+ {
+ ReadExternalApplication(file, i++);
+ }
+ SortAddin();
+ }
+
+ private bool ReadExternalApplication(IniFile file, int nodeNumber)
+ {
+ var text = file.ReadString("ExternalApplications", $"EAClassName{nodeNumber}");
+ var text2 = file.ReadString("ExternalApplications", $"EAAssembly{nodeNumber}");
+ if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2))
+ {
+ return false;
+ }
+ AddItem(new AddinItem(AddinType.Application)
+ {
+ Name = string.Empty,
+ AssemblyPath = text2,
+ FullClassName = text
+ });
+ return true;
+ }
+
+ public void Save(IniFile file)
+ {
+ file.WriteSection("ExternalApplications");
+ file.Write("ExternalApplications", "EACount", m_maxCount);
+ var num = 0;
+ foreach (var addin in m_addinDict.Values)
+ {
+ foreach (var addinItem in addin.ItemList)
+ {
+ if (num >= m_maxCount)
+ {
+ break;
+ }
+ if (addinItem.Save)
+ {
+ WriteExternalApplication(file, addinItem, ++num);
+ }
+ }
+ }
+ file.Write("ExternalApplications", "EACount", num);
+ }
+
+ private bool WriteExternalApplication(IniFile file, AddinItem item, int number)
+ {
+ file.Write("ExternalApplications", $"EAClassName{number}", item.FullClassName);
+ file.Write("ExternalApplications", $"EAAssembly{number}", item.AssemblyPath);
+ return true;
+ }
+ }
+}
diff --git a/AddInManager/AddinsCommand.cs b/AddInManager/AddinsCommand.cs
new file mode 100644
index 0000000..e7217d8
--- /dev/null
+++ b/AddInManager/AddinsCommand.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace AddInManager
+{
+ public class AddinsCommand : Addins
+ {
+ public void ReadItems(IniFile file)
+ {
+ var num = file.ReadInt("ExternalCommands", "ECCount");
+ var i = 1;
+ while (i <= num)
+ {
+ ReadExternalCommand(file, i++);
+ }
+ SortAddin();
+ }
+
+ private bool ReadExternalCommand(IniFile file, int nodeNumber)
+ {
+ var text = file.ReadString("ExternalCommands", $"ECName{nodeNumber}");
+ var text2 = file.ReadString("ExternalCommands", $"ECAssembly{nodeNumber}");
+ var text3 = file.ReadString("ExternalCommands", $"ECClassName{nodeNumber}");
+ var text4 = file.ReadString("ExternalCommands", $"ECDescription{nodeNumber}");
+ if (string.IsNullOrEmpty(text3) || string.IsNullOrEmpty(text2))
+ {
+ return false;
+ }
+ AddItem(new AddinItem(AddinType.Command)
+ {
+ Name = text,
+ AssemblyPath = text2,
+ FullClassName = text3,
+ Description = text4
+ });
+ return true;
+ }
+
+ public void Save(IniFile file)
+ {
+ file.WriteSection("ExternalCommands");
+ file.Write("ExternalCommands", "ECCount", m_maxCount);
+ var num = 0;
+ foreach (var addin in m_addinDict.Values)
+ {
+ foreach (var addinItem in addin.ItemList)
+ {
+ if (num >= m_maxCount)
+ {
+ break;
+ }
+ if (addinItem.Save)
+ {
+ WriteExternalCommand(file, addinItem, ++num);
+ }
+ }
+ }
+ file.Write("ExternalCommands", "ECCount", num);
+ }
+
+ private bool WriteExternalCommand(IniFile file, AddinItem item, int number)
+ {
+ file.Write("ExternalCommands", $"ECName{number}", item.Name);
+ file.Write("ExternalCommands", $"ECClassName{number}", item.FullClassName);
+ file.Write("ExternalCommands", $"ECAssembly{number}", item.AssemblyPath);
+ file.Write("ExternalCommands", $"ECDescription{number}", item.Description);
+ return true;
+ }
+ }
+}
diff --git a/AddInManager/App.cs b/AddInManager/App.cs
new file mode 100644
index 0000000..9f9fc2d
--- /dev/null
+++ b/AddInManager/App.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+using AddInManager.Properties;
+
+using Autodesk.Private.InfoCenter;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+
+
+namespace AddInManager
+{
+ internal class App : IExternalApplication
+ {
+ public static string RevitVersion { get; set; }
+ private static readonly Dictionary KnownAssemblies = new Dictionary(
+ StringComparer.Ordinal)
+ {
+ { "System.Resources.Extensions", "System.Resources.Extensions.dll" },
+ { "System.Runtime.CompilerServices.Unsafe", "System.Runtime.CompilerServices.Unsafe.dll" }
+ };
+ private static readonly ConcurrentDictionary AssemblyCache = new ConcurrentDictionary(StringComparer.Ordinal);
+ private static readonly string BaseDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+
+ public Result OnStartup(UIControlledApplication application)
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+ CreateRibbonPanel(application);
+ return Result.Succeeded;
+ }
+ public Result OnShutdown(UIControlledApplication application)
+ {
+ return Result.Cancelled;
+ }
+ private static void CreateRibbonPanel(UIControlledApplication application)
+ {
+ RevitVersion = application.ControlledApplication.VersionNumber;
+ var ribbonPanel = application.CreateRibbonPanel("开发工具");
+ var pulldownButtonData = new PulldownButtonData("选项", "插件管理");
+ var pulldownButton = (PulldownButton)ribbonPanel.AddItem(pulldownButtonData);
+ pulldownButton.Image = ToImageSource(Resources.Develop_16);
+ pulldownButton.LargeImage = ToImageSource(Resources.Develop_32);
+ AddPushButton(pulldownButton, typeof(CAddInManagerManual), "插件管理(手动模式)");
+ AddPushButton(pulldownButton, typeof(CAddInManagerFaceless), "插件管理(手动模式,无界面)");
+ AddPushButton(pulldownButton, typeof(CAddInManagerReadOnly), "插件管理(只读模式)");
+ var tab = ComponentManager.Ribbon.FindTab("Modify");
+ if (tab != null)
+ {
+ var adwPanel = new Autodesk.Windows.RibbonPanel();
+ adwPanel.CopyFrom(GetRibbonPanel(ribbonPanel));
+ tab.Panels.Add(adwPanel);
+ }
+
+ }
+ internal static BitmapImage ToImageSource(Bitmap bitmap)
+ {
+ var ms = new MemoryStream();
+ bitmap.Save(ms, ImageFormat.Png);
+ var image = new BitmapImage();
+ image.BeginInit();
+ ms.Seek(0, SeekOrigin.Begin);
+ image.StreamSource = ms;
+ image.EndInit();
+ return image;
+ }
+
+ private static readonly FieldInfo RibbonPanelField = typeof(Autodesk.Revit.UI.RibbonPanel).GetField("m_RibbonPanel", BindingFlags.Instance | BindingFlags.NonPublic);
+
+ public static Autodesk.Windows.RibbonPanel GetRibbonPanel(Autodesk.Revit.UI.RibbonPanel panel)
+ {
+ return RibbonPanelField.GetValue(panel) as Autodesk.Windows.RibbonPanel;
+ }
+
+ private static void AddPushButton(PulldownButton pullDownButton, Type command, string buttonText)
+ {
+ var buttonData = new PushButtonData(command.FullName, buttonText, Assembly.GetAssembly(command).Location, command.FullName);
+ pullDownButton.AddPushButton(buttonData);
+ }
+
+ private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ var requestedAssemblyName = new AssemblyName(args.Name).Name;
+ if (AssemblyCache.TryGetValue(requestedAssemblyName, out var cachedAssembly))
+ {
+ return cachedAssembly;
+ }
+ if (KnownAssemblies.TryGetValue(requestedAssemblyName, out var assemblyFile))
+ {
+ var assemblyPath = Path.Combine(BaseDirectory, assemblyFile);
+
+ try
+ {
+ var assembly = Assembly.LoadFrom(assemblyPath);
+ AssemblyCache.TryAdd(requestedAssemblyName, assembly);
+ return assembly;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ }
+ }
+
+ return null;
+ }
+
+ }
+}
diff --git a/AddInManager/AssemLoader.cs b/AddInManager/AssemLoader.cs
new file mode 100644
index 0000000..0cacb10
--- /dev/null
+++ b/AddInManager/AssemLoader.cs
@@ -0,0 +1,275 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+
+namespace AddInManager
+{
+ public class AssemLoader
+ {
+ public string OriginalFolder { get; set; }
+
+ public string TempFolder { get; set; }
+
+ public AssemLoader()
+ {
+ TempFolder = string.Empty;
+ m_refedFolders = new List();
+ m_copiedFiles = new Dictionary();
+ }
+
+ public void CopyGeneratedFilesBack()
+ {
+ var files = Directory.GetFiles(TempFolder, "*.*", SearchOption.AllDirectories);
+ foreach (var text in files)
+ {
+ if (m_copiedFiles.ContainsKey(text))
+ {
+ var dateTime = m_copiedFiles[text];
+ var fileInfo = new FileInfo(text);
+ if (fileInfo.LastWriteTime > dateTime)
+ {
+ var text2 = text.Remove(0, TempFolder.Length);
+ var text3 = OriginalFolder + text2;
+ FileUtils.CopyFile(text, text3);
+ }
+ }
+ else
+ {
+ var text4 = text.Remove(0, TempFolder.Length);
+ var text5 = OriginalFolder + text4;
+ FileUtils.CopyFile(text, text5);
+ }
+ }
+ }
+
+ public void HookAssemblyResolve()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+ }
+
+ public void UnhookAssemblyResolve()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
+ }
+
+ public Assembly LoadAddinsToTempFolder(string originalFilePath, bool parsingOnly)
+ {
+ if (string.IsNullOrEmpty(originalFilePath) || originalFilePath.StartsWith("\\") || !File.Exists(originalFilePath))
+ {
+ return null;
+ }
+ m_parsingOnly = parsingOnly;
+ OriginalFolder = Path.GetDirectoryName(originalFilePath);
+ var stringBuilder = new StringBuilder(Path.GetFileNameWithoutExtension(originalFilePath));
+ if (parsingOnly)
+ {
+ stringBuilder.Append("-Parsing-");
+ }
+ else
+ {
+ stringBuilder.Append("-Executing-");
+ }
+ TempFolder = FileUtils.CreateTempFolder(stringBuilder.ToString());
+ var assembly = CopyAndLoadAddin(originalFilePath, parsingOnly);
+ if (null == assembly || !IsAPIReferenced(assembly))
+ {
+ return null;
+ }
+ return assembly;
+ }
+
+ private Assembly CopyAndLoadAddin(string srcFilePath, bool onlyCopyRelated)
+ {
+ var text = string.Empty;
+ if (!FileUtils.FileExistsInFolder(srcFilePath, TempFolder))
+ {
+ var directoryName = Path.GetDirectoryName(srcFilePath);
+ if (!m_refedFolders.Contains(directoryName))
+ {
+ m_refedFolders.Add(directoryName);
+ }
+ var list = new List();
+ text = FileUtils.CopyFileToFolder(srcFilePath, TempFolder, onlyCopyRelated, list);
+ if (string.IsNullOrEmpty(text))
+ {
+ return null;
+ }
+ foreach (var fileInfo in list)
+ {
+ m_copiedFiles.Add(fileInfo.FullName, fileInfo.LastWriteTime);
+ }
+ }
+ return LoadAddin(text);
+ }
+
+ private Assembly LoadAddin(string filePath)
+ {
+ Assembly assembly = null;
+ try
+ {
+ Monitor.Enter(this);
+ assembly = Assembly.LoadFile(filePath);
+ }
+ finally
+ {
+ Monitor.Exit(this);
+ }
+ return assembly;
+ }
+
+ private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ Assembly assembly;
+ lock (this)
+ {
+ new AssemblyName(args.Name);
+ var text = SearchAssemblyFileInTempFolder(args.Name);
+ if (File.Exists(text))
+ {
+ assembly = LoadAddin(text);
+ }
+ else
+ {
+ text = SearchAssemblyFileInOriginalFolders(args.Name);
+ if (string.IsNullOrEmpty(text))
+ {
+ var array = args.Name.Split(new char[] { ',' });
+ var text2 = array[0];
+ if (array.Length > 1)
+ {
+ var text3 = array[2];
+ if (text2.EndsWith(".resources", StringComparison.CurrentCultureIgnoreCase) && !text3.EndsWith("neutral", StringComparison.CurrentCultureIgnoreCase))
+ {
+ text2 = text2.Substring(0, text2.Length - ".resources".Length);
+ }
+ text = SearchAssemblyFileInTempFolder(text2);
+ if (File.Exists(text))
+ {
+ return LoadAddin(text);
+ }
+ text = SearchAssemblyFileInOriginalFolders(text2);
+ }
+ }
+ if (string.IsNullOrEmpty(text))
+ {
+ var assemblySelector = new Wpf.AssemblySelectorWindow(args.Name);
+ if (assemblySelector.ShowDialog() != true)
+ {
+ return null;
+ }
+ text = assemblySelector.ResultPath;
+ }
+ assembly = CopyAndLoadAddin(text, true);
+ }
+ }
+ return assembly;
+ }
+
+ private string SearchAssemblyFileInTempFolder(string assemName)
+ {
+ var array = new string[] { ".dll", ".exe" };
+ var text = string.Empty;
+ var text2 = assemName.Substring(0, assemName.IndexOf(','));
+ foreach (var text3 in array)
+ {
+ text = $"{TempFolder}\\{text2}{text3}";
+ if (File.Exists(text))
+ {
+ return text;
+ }
+ }
+ return string.Empty;
+ }
+
+ private string SearchAssemblyFileInOriginalFolders(string assemName)
+ {
+ var array = new string[] { ".dll", ".exe" };
+ var text = string.Empty;
+ var text2 = assemName.Substring(0, assemName.IndexOf(','));
+ foreach (var text3 in array)
+ {
+ text = $"{m_dotnetDir}\\{text2}{text3}";
+ if (File.Exists(text))
+ {
+ return text;
+ }
+ }
+ foreach (var text4 in array)
+ {
+ foreach (var text5 in m_refedFolders)
+ {
+ text = $"{text5}\\{text2}{text4}";
+ if (File.Exists(text))
+ {
+ return text;
+ }
+ }
+ }
+ try
+ {
+ var directoryInfo = new DirectoryInfo(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName));
+ var text6 = $"{directoryInfo.Parent.FullName}\\Regression\\_RegressionTools\\";
+ if (Directory.Exists(text6))
+ {
+ foreach (var text7 in Directory.GetFiles(text6, "*.*", SearchOption.AllDirectories))
+ {
+ if (Path.GetFileNameWithoutExtension(text7).Equals(text2, StringComparison.OrdinalIgnoreCase))
+ {
+ return text7;
+ }
+ }
+ }
+ }
+ catch (Exception)
+ {
+ }
+ var num = assemName.IndexOf("XMLSerializers", StringComparison.OrdinalIgnoreCase);
+ if (num != -1)
+ {
+ assemName = $"System.XML{assemName.Substring(num + "XMLSerializers".Length)}";
+ return SearchAssemblyFileInOriginalFolders(assemName);
+ }
+ return null;
+ }
+
+ private bool IsAPIReferenced(Assembly assembly)
+ {
+ if (string.IsNullOrEmpty(m_revitAPIAssemblyFullName))
+ {
+ foreach (var assembly2 in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ if (string.Compare(assembly2.GetName().Name, "RevitAPI", true) == 0)
+ {
+ m_revitAPIAssemblyFullName = assembly2.GetName().Name;
+ break;
+ }
+ }
+ }
+ foreach (var assemblyName in assembly.GetReferencedAssemblies())
+ {
+ if (m_revitAPIAssemblyFullName == assemblyName.Name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private List m_refedFolders;
+
+ private Dictionary m_copiedFiles;
+
+ private bool m_parsingOnly;
+
+ private static string m_dotnetDir =
+ $"{Environment.GetEnvironmentVariable("windir")}\\Microsoft.NET\\Framework\\v2.0.50727";
+
+ public static string m_resolvedAssemPath = string.Empty;
+
+ private string m_revitAPIAssemblyFullName;
+ }
+}
diff --git a/AddInManager/CAddInManagerFaceless.cs b/AddInManager/CAddInManagerFaceless.cs
new file mode 100644
index 0000000..d2ec081
--- /dev/null
+++ b/AddInManager/CAddInManagerFaceless.cs
@@ -0,0 +1,19 @@
+
+using Autodesk.Revit.Attributes;
+
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+
+using System;
+
+namespace AddInManager
+{
+ [Transaction(TransactionMode.Manual)]
+ public class CAddInManagerFaceless : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData revit, ref string message, ElementSet elements)
+ {
+ return AIM.Instance.ExecuteCommand(revit, ref message, elements, true);
+ }
+ }
+}
diff --git a/AddInManager/CAddInManagerManual.cs b/AddInManager/CAddInManagerManual.cs
new file mode 100644
index 0000000..5d268a4
--- /dev/null
+++ b/AddInManager/CAddInManagerManual.cs
@@ -0,0 +1,40 @@
+using Autodesk.Revit.Attributes;
+using Autodesk.Revit.UI;
+
+using System;
+using System.Windows;
+
+namespace AddInManager
+{
+ [Transaction(TransactionMode.Manual)]
+ public class CAddInManagerManual : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
+ {
+ try
+ {
+ var aim = AIM.Instance;
+ var window = new Wpf.MainWindow(aim)
+ {
+ WindowStartupLocation = WindowStartupLocation.CenterScreen
+ };
+
+ var dialogResult = window.ShowDialog();
+
+ // 检查是否需要执行命令
+ if (dialogResult == true && aim.ActiveCmd != null && aim.ActiveCmdItem != null)
+ {
+ // 调用AIM的ExecuteCommand方法来执行选中的命令
+ return aim.ExecuteCommand(commandData, ref message, elements, true);
+ }
+
+ return Result.Succeeded;
+ }
+ catch (Exception ex)
+ {
+ message = ex.Message;
+ return Result.Failed;
+ }
+ }
+ }
+}
diff --git a/AddInManager/CAddInManagerReadOnly.cs b/AddInManager/CAddInManagerReadOnly.cs
new file mode 100644
index 0000000..a199df3
--- /dev/null
+++ b/AddInManager/CAddInManagerReadOnly.cs
@@ -0,0 +1,33 @@
+using Autodesk.Revit.Attributes;
+using Autodesk.Revit.UI;
+
+using System;
+using System.Windows;
+
+namespace AddInManager
+{
+ [Transaction(TransactionMode.ReadOnly)]
+ public class CAddInManagerReadOnly : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
+ {
+ try
+ {
+ var aim = AIM.Instance;
+
+ var window = new Wpf.MainWindow(aim)
+ {
+ WindowStartupLocation = WindowStartupLocation.CenterScreen
+ };
+ window.ShowDialog();
+
+ return Result.Succeeded;
+ }
+ catch (Exception ex)
+ {
+ message = ex.Message;
+ return Result.Failed;
+ }
+ }
+ }
+}
diff --git a/AddInManager/FailedToRunECDialog.cs b/AddInManager/FailedToRunECDialog.cs
new file mode 100644
index 0000000..adb373b
--- /dev/null
+++ b/AddInManager/FailedToRunECDialog.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Windows;
+
+using AddInManager.Properties;
+
+namespace AddInManager
+{
+ public class FailedToRunECDialog
+ {
+ public static MessageBoxResult Show(string ecName)
+ {
+ var text = $"选中外部命令 [{ecName}] 返回 \"Result.Failed\",请检查测试脚本";
+ return MessageBox.Show(text, Resources.AppName, MessageBoxButton.OK);
+ }
+ }
+}
diff --git a/AddInManager/FileUtils.cs b/AddInManager/FileUtils.cs
new file mode 100644
index 0000000..14f8b16
--- /dev/null
+++ b/AddInManager/FileUtils.cs
@@ -0,0 +1,239 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Windows;
+
+namespace AddInManager
+{
+ public static class FileUtils
+ {
+ public static DateTime GetModifyTime(string filePath)
+ {
+ return File.GetLastWriteTime(filePath);
+ }
+
+ public static string CreateTempFolder(string prefix)
+ {
+ var tempPath = Path.GetTempPath();
+ var directoryInfo = new DirectoryInfo(Path.Combine(tempPath, "RevitAddins"));
+ if (!directoryInfo.Exists)
+ {
+ directoryInfo.Create();
+ }
+ foreach (var directoryInfo2 in directoryInfo.GetDirectories())
+ {
+ try
+ {
+ Directory.Delete(directoryInfo2.FullName, true);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ var text = string.Format("{0:yyyyMMdd_HHmmss_ffff}", DateTime.Now);
+ var text2 = Path.Combine(directoryInfo.FullName, prefix + text);
+ var directoryInfo3 = new DirectoryInfo(text2);
+ directoryInfo3.Create();
+ return directoryInfo3.FullName;
+ }
+
+ public static void SetWriteable(string fileName)
+ {
+ if (File.Exists(fileName))
+ {
+ var fileAttributes = File.GetAttributes(fileName) & ~FileAttributes.ReadOnly;
+ File.SetAttributes(fileName, fileAttributes);
+ }
+ }
+
+ public static bool SameFile(string file1, string file2)
+ {
+ return 0 == string.Compare(file1.Trim(), file2.Trim(), true);
+ }
+
+ public static bool CreateFile(string filePath)
+ {
+ if (File.Exists(filePath))
+ {
+ return true;
+ }
+ try
+ {
+ var directoryName = Path.GetDirectoryName(filePath);
+ if (!Directory.Exists(directoryName))
+ {
+ Directory.CreateDirectory(directoryName);
+ }
+ using (new FileInfo(filePath).Create())
+ {
+ SetWriteable(filePath);
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ return File.Exists(filePath);
+ }
+
+ public static void DeleteFile(string fileName)
+ {
+ if (File.Exists(fileName))
+ {
+ var fileAttributes = File.GetAttributes(fileName) & ~FileAttributes.ReadOnly;
+ File.SetAttributes(fileName, fileAttributes);
+ try
+ {
+ File.Delete(fileName);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ public static bool FileExistsInFolder(string filePath, string destFolder)
+ {
+ var text = Path.Combine(destFolder, Path.GetFileName(filePath));
+ return File.Exists(text);
+ }
+
+ public static string CopyFileToFolder(string sourceFilePath, string destFolder, bool onlyCopyRelated, List allCopiedFiles)
+ {
+ if (!File.Exists(sourceFilePath))
+ {
+ return null;
+ }
+ var directoryName = Path.GetDirectoryName(sourceFilePath);
+ if (onlyCopyRelated)
+ {
+ var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(sourceFilePath);
+ var text = $"{fileNameWithoutExtension}.*";
+ var files = Directory.GetFiles(directoryName, text, SearchOption.TopDirectoryOnly);
+ foreach (var text2 in files)
+ {
+ var fileName = Path.GetFileName(text2);
+ var text3 = Path.Combine(destFolder, fileName);
+ var flag = CopyFile(text2, text3);
+ if (flag)
+ {
+ var fileInfo = new FileInfo(text3);
+ allCopiedFiles.Add(fileInfo);
+ }
+ }
+ }
+ else
+ {
+ var folderSize = GetFolderSize(directoryName);
+ if (folderSize > 50L)
+ {
+ var result = FolderTooBigDialog.Show(directoryName, folderSize);
+ switch (result)
+ {
+ case MessageBoxResult.Yes:
+ CopyDirectory(directoryName, destFolder, allCopiedFiles);
+ break;
+ case MessageBoxResult.No:
+ CopyFileToFolder(sourceFilePath, destFolder, true, allCopiedFiles);
+ break;
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ CopyDirectory(directoryName, destFolder, allCopiedFiles);
+ }
+ }
+ var text4 = Path.Combine(destFolder, Path.GetFileName(sourceFilePath));
+ if (File.Exists(text4))
+ {
+ return text4;
+ }
+ return null;
+ }
+
+ public static bool CopyFile(string sourceFilename, string destinationFilename)
+ {
+ if (!File.Exists(sourceFilename))
+ {
+ return false;
+ }
+ var fileAttributes = File.GetAttributes(sourceFilename) & ~FileAttributes.ReadOnly;
+ File.SetAttributes(sourceFilename, fileAttributes);
+ if (File.Exists(destinationFilename))
+ {
+ var fileAttributes2 = File.GetAttributes(destinationFilename) & ~FileAttributes.ReadOnly;
+ File.SetAttributes(destinationFilename, fileAttributes2);
+ File.Delete(destinationFilename);
+ }
+ try
+ {
+ if (!Directory.Exists(Path.GetDirectoryName(destinationFilename)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(destinationFilename));
+ }
+ File.Copy(sourceFilename, destinationFilename, true);
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ return File.Exists(destinationFilename);
+ }
+
+ public static void CopyDirectory(string sourceDir, string desDir, List allCopiedFiles)
+ {
+ try
+ {
+ var directories = Directory.GetDirectories(sourceDir, "*.*", SearchOption.AllDirectories);
+ foreach (var text in directories)
+ {
+ var text2 = text.Replace(sourceDir, string.Empty);
+ var text3 = desDir + text2;
+ if (!Directory.Exists(text3))
+ {
+ Directory.CreateDirectory(text3);
+ }
+ }
+ var files = Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories);
+ foreach (var text4 in files)
+ {
+ var text5 = text4.Replace(sourceDir, string.Empty);
+ var text6 = desDir + text5;
+ if (!Directory.Exists(Path.GetDirectoryName(text6)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(text6));
+ }
+ if (CopyFile(text4, text6))
+ {
+ allCopiedFiles.Add(new FileInfo(text6));
+ }
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ public static long GetFolderSize(string folderPath)
+ {
+ var directoryInfo = new DirectoryInfo(folderPath);
+ var num = 0L;
+ foreach (var fileSystemInfo in directoryInfo.GetFileSystemInfos())
+ {
+ if (fileSystemInfo is FileInfo)
+ {
+ num += ((FileInfo)fileSystemInfo).Length;
+ }
+ else
+ {
+ num += GetFolderSize(fileSystemInfo.FullName);
+ }
+ }
+ return num / 1024L / 1024L;
+ }
+
+ private const string TempFolderName = "RevitAddins";
+ }
+}
diff --git a/AddInManager/FolderTooBigDialog.cs b/AddInManager/FolderTooBigDialog.cs
new file mode 100644
index 0000000..4456102
--- /dev/null
+++ b/AddInManager/FolderTooBigDialog.cs
@@ -0,0 +1,24 @@
+using AddInManager.Properties;
+
+using System;
+using System.Text;
+using System.Windows;
+
+namespace AddInManager
+{
+ public abstract class FolderTooBigDialog
+ {
+ public static MessageBoxResult Show(string folderPath, long sizeInMB)
+ {
+ var stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine($"文件夹[{folderPath}]");
+ stringBuilder.AppendLine($"有{sizeInMB}MB大小");
+ stringBuilder.AppendLine("AddinManager尝试复制所有文件到临时文件夹");
+ stringBuilder.AppendLine("选择[Yes]复制所有文件到临时文件夹");
+ stringBuilder.AppendLine("选择[No]仅复制测试DLL文件到临时文件夹");
+ stringBuilder.AppendLine("选择[Cancel]取消操作");
+ var text = stringBuilder.ToString();
+ return MessageBox.Show(text, Resources.AppName, MessageBoxButton.YesNoCancel, MessageBoxImage.Information, MessageBoxResult.Yes);
+ }
+ }
+}
diff --git a/AddInManager/IAddinNode.cs b/AddInManager/IAddinNode.cs
new file mode 100644
index 0000000..f05171d
--- /dev/null
+++ b/AddInManager/IAddinNode.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace AddInManager
+{
+ public interface IAddinNode
+ {
+ bool Save { get; set; }
+
+ bool Hidden { get; set; }
+ }
+}
diff --git a/AddInManager/IniFile.cs b/AddInManager/IniFile.cs
new file mode 100644
index 0000000..1fc7866
--- /dev/null
+++ b/AddInManager/IniFile.cs
@@ -0,0 +1,56 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace AddInManager
+{
+ public class IniFile
+ {
+ public string FilePath { get; }
+
+ public IniFile(string filePath)
+ {
+ FilePath = filePath;
+ if (!File.Exists(FilePath))
+ {
+ FileUtils.CreateFile(FilePath);
+ FileUtils.SetWriteable(FilePath);
+ }
+ }
+
+ public void WriteSection(string iniSection)
+ {
+ WritePrivateProfileSection(iniSection, null, FilePath);
+ }
+
+ public void Write(string iniSection, string iniKey, object iniValue)
+ {
+ WritePrivateProfileString(iniSection, iniKey, iniValue.ToString(), FilePath);
+ }
+
+ public string ReadString(string iniSection, string iniKey)
+ {
+ var stringBuilder = new StringBuilder(255);
+ GetPrivateProfileString(iniSection, iniKey, string.Empty, stringBuilder, 255, FilePath);
+ return stringBuilder.ToString();
+ }
+
+ public int ReadInt(string iniSection, string iniKey)
+ {
+ return GetPrivateProfileInt(iniSection, iniKey, 0, FilePath);
+ }
+
+ [DllImport("kernel32.dll")]
+ private static extern int WritePrivateProfileSection(string lpAppName, string lpString, string lpFileName);
+
+ [DllImport("kernel32", CharSet = CharSet.Auto)]
+ private static extern int WritePrivateProfileString(string section, string key, string val, string filePath);
+
+ [DllImport("kernel32")]
+ private static extern int GetPrivateProfileInt(string section, string key, int def, string filePath);
+
+ [DllImport("kernel32", CharSet = CharSet.Auto)]
+ private static extern int GetPrivateProfileString(string section, string key, string defaultValue, StringBuilder retVal, int size, string filePath);
+ }
+}
diff --git a/AddInManager/ManifestFile.cs b/AddInManager/ManifestFile.cs
new file mode 100644
index 0000000..ccf0d2a
--- /dev/null
+++ b/AddInManager/ManifestFile.cs
@@ -0,0 +1,392 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+
+namespace AddInManager
+{
+ public class ManifestFile
+ {
+ public ManifestFile()
+ {
+ Local = false;
+ Applications = new List();
+ Commands = new List();
+ }
+
+ public ManifestFile(string fileName) : this()
+ {
+ FileName = fileName;
+ if (!string.IsNullOrEmpty(m_filePath)) return;
+ var text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AddIn");
+ m_filePath = Path.Combine(text, FileName);
+ }
+
+ public ManifestFile(bool local) : this()
+ {
+ Local = local;
+ }
+
+ public void Load()
+ {
+ m_xmlDoc = new XmlDocument();
+ m_xmlDoc.Load(m_filePath);
+ var documentElement = m_xmlDoc.DocumentElement;
+ if (!documentElement.Name.Equals(ROOT_NODE))
+ {
+ throw new System.ArgumentException(INCORRECT_NODE);
+ }
+ if (documentElement.ChildNodes.Count == 0)
+ {
+ throw new System.ArgumentException(EMPTY_ADDIN);
+ }
+ Applications.Clear();
+ Commands.Clear();
+ foreach (var obj in documentElement.ChildNodes)
+ {
+ var xmlNode = (XmlNode)obj;
+ if (!xmlNode.Name.Equals(ADDIN_NODE) || xmlNode.Attributes.Count != 1)
+ {
+ throw new System.ArgumentException(INCORRECT_NODE);
+ }
+ var xmlAttribute = xmlNode.Attributes[0];
+ if (xmlAttribute.Value.Equals(APPLICATION_NODE))
+ {
+ ParseExternalApplications(xmlNode);
+ }
+ else
+ {
+ if (!xmlAttribute.Value.Equals(COMMAND_NODE))
+ {
+ throw new System.ArgumentException(INCORRECT_NODE);
+ }
+ ParseExternalCommands(xmlNode);
+ }
+ }
+ }
+
+ public void Save()
+ {
+ SaveAs(m_filePath);
+ }
+
+ public void SaveAs(string filePath)
+ {
+ if (string.IsNullOrEmpty(filePath))
+ {
+ throw new System.ArgumentNullException(FILENAME_NULL_OR_EMPTY);
+ }
+ if (!filePath.ToLower().EndsWith(ADDIN))
+ {
+ throw new System.ArgumentException(FILENAME_INCORRECT_WARNING + filePath);
+ }
+ var directoryName = Path.GetDirectoryName(filePath);
+ if (!Directory.Exists(directoryName))
+ {
+ Directory.CreateDirectory(directoryName);
+ }
+ var fileInfo = new FileInfo(filePath);
+ m_xmlDoc = new XmlDocument();
+ CreateXMLForManifest();
+ if (File.Exists(filePath))
+ {
+ File.SetAttributes(filePath, FileAttributes.Normal);
+ }
+ TextWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
+ var xmlTextWriter = new XmlTextWriter(textWriter);
+ xmlTextWriter.Formatting = Formatting.Indented;
+ m_xmlDoc.Save(xmlTextWriter);
+ xmlTextWriter.Close();
+ m_filePath = fileInfo.FullName;
+ FileName = Path.GetFileName(fileInfo.FullName);
+ }
+
+ public string FileName { get; set; }
+
+ public bool Local { get; set; }
+
+ public string FilePath
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(m_filePath))
+ {
+ var text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AddIn");
+ m_filePath = Path.Combine(text, "AimInternal.ini");
+ }
+ return m_filePath;
+ }
+ set => m_filePath = value;
+ }
+
+ public List Applications { get; set; }
+
+ public List Commands { get; set; }
+
+ private XmlDocument CreateXMLForManifest()
+ {
+ var xmlNode = m_xmlDoc.AppendChild(m_xmlDoc.CreateElement(ROOT_NODE));
+ foreach (var addinItem in Applications)
+ {
+ var xmlElement = m_xmlDoc.CreateElement(ADDIN_NODE);
+ xmlElement.SetAttribute(TYPE_ATTRIBUTE, APPLICATION_NODE);
+ xmlNode.AppendChild(xmlElement);
+ AddApplicationToXmlElement(xmlElement, addinItem);
+ var xmlElement2 = m_xmlDoc.CreateElement(VENDORID);
+ xmlElement2.InnerText = "ADSK";
+ xmlElement.AppendChild(xmlElement2);
+ xmlElement2 = m_xmlDoc.CreateElement(VENDORDESCRIPTION);
+ xmlElement2.InnerText = "Autodesk, www.autodesk.com";
+ xmlElement.AppendChild(xmlElement2);
+ }
+ foreach (var addinItem2 in Commands)
+ {
+ var xmlElement3 = m_xmlDoc.CreateElement(ADDIN_NODE);
+ xmlElement3.SetAttribute(TYPE_ATTRIBUTE, COMMAND_NODE);
+ xmlNode.AppendChild(xmlElement3);
+ AddCommandToXmlElement(xmlElement3, addinItem2);
+ var xmlElement4 = m_xmlDoc.CreateElement(VENDORID);
+ xmlElement4.InnerText = "ADSK";
+ xmlElement3.AppendChild(xmlElement4);
+ xmlElement4 = m_xmlDoc.CreateElement(VENDORDESCRIPTION);
+ xmlElement4.InnerText = "Autodesk, www.autodesk.com";
+ xmlElement3.AppendChild(xmlElement4);
+ }
+ return m_xmlDoc;
+ }
+
+ private void AddAddInItemToXmlElement(XmlElement xmlEle, AddinItem addinItem)
+ {
+ if (!string.IsNullOrEmpty(addinItem.AssemblyPath))
+ {
+ var xmlElement = m_xmlDoc.CreateElement(ASSEMBLY);
+ if (Local)
+ {
+ xmlElement.InnerText = addinItem.AssemblyName;
+ }
+ else
+ {
+ xmlElement.InnerText = addinItem.AssemblyPath;
+ }
+ xmlEle.AppendChild(xmlElement);
+ }
+ if (!string.IsNullOrEmpty(addinItem.ClientIdString))
+ {
+ var xmlElement2 = m_xmlDoc.CreateElement(CLIENTID);
+ xmlElement2.InnerText = addinItem.ClientIdString;
+ xmlEle.AppendChild(xmlElement2);
+ }
+ if (!string.IsNullOrEmpty(addinItem.FullClassName))
+ {
+ var xmlElement3 = m_xmlDoc.CreateElement(FULLCLASSNAME);
+ xmlElement3.InnerText = addinItem.FullClassName;
+ xmlEle.AppendChild(xmlElement3);
+ }
+ }
+
+ private void AddApplicationToXmlElement(XmlElement appEle, AddinItem currentApp)
+ {
+ if (!string.IsNullOrEmpty(currentApp.Name))
+ {
+ var xmlElement = m_xmlDoc.CreateElement(NAME_NODE);
+ xmlElement.InnerText = currentApp.Name;
+ appEle.AppendChild(xmlElement);
+ }
+ AddAddInItemToXmlElement(appEle, currentApp);
+ }
+
+ private void AddCommandToXmlElement(XmlElement commandEle, AddinItem command)
+ {
+ AddAddInItemToXmlElement(commandEle, command);
+ XmlElement xmlElement;
+ if (!string.IsNullOrEmpty(command.Name))
+ {
+ xmlElement = m_xmlDoc.CreateElement(TEXT);
+ xmlElement.InnerText = command.Name;
+ commandEle.AppendChild(xmlElement);
+ }
+ if (!string.IsNullOrEmpty(command.Description))
+ {
+ xmlElement = m_xmlDoc.CreateElement(DESCRIPTION);
+ xmlElement.InnerText = command.Description;
+ commandEle.AppendChild(xmlElement);
+ }
+ var text = command.VisibilityMode.ToString();
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Replace(",", " |");
+ }
+ xmlElement = m_xmlDoc.CreateElement(VISIBILITYMODE);
+ xmlElement.InnerText = text;
+ commandEle.AppendChild(xmlElement);
+ }
+
+ private void ParseExternalApplications(XmlNode nodeApplication)
+ {
+ var addinItem = new AddinItem(AddinType.Application);
+ parseApplicationItems(addinItem, nodeApplication);
+ Applications.Add(addinItem);
+ }
+
+ private void ParseExternalCommands(XmlNode nodeCommand)
+ {
+ var addinItem = new AddinItem(AddinType.Command);
+ ParseCommandItems(addinItem, nodeCommand);
+ Commands.Add(addinItem);
+ }
+
+ private void parseApplicationItems(AddinItem addinApp, XmlNode nodeAddIn)
+ {
+ ParseAddInItem(addinApp, nodeAddIn);
+ var xmlElement = nodeAddIn[NAME_NODE];
+ if (xmlElement != null && !string.IsNullOrEmpty(xmlElement.InnerText))
+ {
+ addinApp.Name = xmlElement.InnerText;
+ }
+ }
+
+ private void ParseCommandItems(AddinItem command, XmlNode nodeAddIn)
+ {
+ ParseAddInItem(command, nodeAddIn);
+ var xmlElement = nodeAddIn[TEXT];
+ if (xmlElement != null)
+ {
+ command.Name = xmlElement.InnerText;
+ }
+ xmlElement = nodeAddIn[DESCRIPTION];
+ if (xmlElement != null)
+ {
+ command.Description = xmlElement.InnerText;
+ }
+ xmlElement = nodeAddIn[VISIBILITYMODE];
+ if (xmlElement != null && !string.IsNullOrEmpty(xmlElement.InnerText))
+ {
+ command.VisibilityMode = parseVisibilityMode(xmlElement.InnerText);
+ }
+ }
+
+ private void ParseAddInItem(AddinItem addinItem, XmlNode nodeAddIn)
+ {
+ var xmlElement = nodeAddIn[ASSEMBLY];
+ if (xmlElement != null)
+ {
+ if (Local)
+ {
+ addinItem.AssemblyName = xmlElement.InnerText;
+ }
+ else
+ {
+ addinItem.AssemblyPath = xmlElement.InnerText;
+ }
+ }
+ xmlElement = nodeAddIn[CLIENTID];
+ if (xmlElement != null)
+ {
+ try
+ {
+ if (!string.IsNullOrEmpty(xmlElement.InnerText))
+ {
+ addinItem.ClientId = new Guid(xmlElement.InnerText);
+ }
+ else
+ {
+ addinItem.ClientId = Guid.Empty;
+ }
+ }
+ catch (Exception)
+ {
+ addinItem.ClientId = Guid.Empty;
+ addinItem.ClientIdString = xmlElement.InnerText;
+ }
+ }
+ xmlElement = nodeAddIn[FULLCLASSNAME];
+ if (xmlElement != null)
+ {
+ addinItem.FullClassName = xmlElement.InnerText;
+ }
+ }
+
+ private VisibilityMode parseVisibilityMode(string visibilityModeString)
+ {
+ var visibilityMode = VisibilityMode.AlwaysVisible;
+ VisibilityMode visibilityMode3;
+ try
+ {
+ var text = "|";
+ var array = text.ToCharArray();
+ var array2 = visibilityModeString.Replace(" | ", "|").Split(array);
+ foreach (var text2 in array2)
+ {
+ var visibilityMode2 = (VisibilityMode)Enum.Parse(typeof(VisibilityMode), text2);
+ visibilityMode |= visibilityMode2;
+ }
+ visibilityMode3 = visibilityMode;
+ }
+ catch (Exception)
+ {
+ throw new System.ArgumentException(UNKNOW_VISIBILITYMODE);
+ }
+ return visibilityMode3;
+ }
+
+ private string getFullPath(string fileName)
+ {
+ FileInfo fileInfo = null;
+ try
+ {
+ fileInfo = new FileInfo(fileName);
+ }
+ catch (Exception ex)
+ {
+ throw new System.ArgumentException(fileName + Environment.NewLine + ex.ToString());
+ }
+ return fileInfo.FullName;
+ }
+
+ private string m_filePath;
+
+ private string ROOT_NODE = "RevitAddIns";
+
+ private string ADDIN_NODE = "AddIn";
+
+ private string APPLICATION_NODE = "Application";
+
+ private string COMMAND_NODE = "Command";
+
+ private string TYPE_ATTRIBUTE = "Type";
+
+ private string INCORRECT_NODE = "incorrect node in addin file!";
+
+ private string EMPTY_ADDIN = "empty addin file!";
+
+ private string ASSEMBLY = "Assembly";
+
+ private string CLIENTID = "ClientId";
+
+ private string FULLCLASSNAME = "FullClassName";
+
+ private string NAME_NODE = "Name";
+
+ private string TEXT = "Text";
+
+ private string DESCRIPTION = "Description";
+
+ private string VENDORID = "VendorId";
+
+ private string VENDORDESCRIPTION = "VendorDescription";
+
+ private string VISIBILITYMODE = "VisibilityMode";
+
+ private string UNKNOW_VISIBILITYMODE = "Unrecognizable VisibilityMode!";
+
+ private string ADDIN = ".addin";
+
+ private string FILENAME_INCORRECT_WARNING = "File name is incorrect, not .addin file .";
+
+ private string FILENAME_NULL_OR_EMPTY = "File name for RevitAddInManifest is null or empty";
+
+ private XmlDocument m_xmlDoc;
+ }
+}
diff --git a/AddInManager/Properties/Resources.Designer.cs b/AddInManager/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..0f42d68
--- /dev/null
+++ b/AddInManager/Properties/Resources.Designer.cs
@@ -0,0 +1,137 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace AddInManager.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AddInManager.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// 查找类似 AddinManager 的本地化字符串。
+ ///
+ internal static string AppName {
+ get {
+ return ResourceManager.GetString("AppName", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap Develop_16 {
+ get {
+ object obj = ResourceManager.GetObject("Develop_16", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// 查找 System.Drawing.Bitmap 类型的本地化资源。
+ ///
+ internal static System.Drawing.Bitmap Develop_32 {
+ get {
+ object obj = ResourceManager.GetObject("Develop_32", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// 查找类似 取消加载 的本地化字符串。
+ ///
+ internal static string LoadCancelled {
+ get {
+ return ResourceManager.GetString("LoadCancelled", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 加载失败 的本地化字符串。
+ ///
+ internal static string LoadFailed {
+ get {
+ return ResourceManager.GetString("LoadFailed", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Revit Addin Files(*.dll)|*.dll 的本地化字符串。
+ ///
+ internal static string LoadFileFilter {
+ get {
+ return ResourceManager.GetString("LoadFileFilter", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 加载成功 的本地化字符串。
+ ///
+ internal static string LoadSucceed {
+ get {
+ return ResourceManager.GetString("LoadSucceed", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 未选中项 的本地化字符串。
+ ///
+ internal static string NoItemsSelected {
+ get {
+ return ResourceManager.GetString("NoItemsSelected", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/AddInManager/Properties/Resources.resx b/AddInManager/Properties/Resources.resx
new file mode 100644
index 0000000..c51c79b
--- /dev/null
+++ b/AddInManager/Properties/Resources.resx
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ AddinManager
+
+
+
+ ..\Resources\Develop_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\Develop_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ 取消加载
+
+
+ 加载失败
+
+
+ Revit Addin Files(*.dll)|*.dll
+
+
+ 加载成功
+
+
+ 未选中项
+
+
\ No newline at end of file
diff --git a/AddInManager/Properties/Settings.Designer.cs b/AddInManager/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..d24e934
--- /dev/null
+++ b/AddInManager/Properties/Settings.Designer.cs
@@ -0,0 +1,38 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace AddInManager.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("RevitAddInManager")]
+ public string AppFolder {
+ get {
+ return ((string)(this["AppFolder"]));
+ }
+ set {
+ this["AppFolder"] = value;
+ }
+ }
+ }
+}
diff --git a/AddInManager/Properties/Settings.settings b/AddInManager/Properties/Settings.settings
new file mode 100644
index 0000000..7d75a79
--- /dev/null
+++ b/AddInManager/Properties/Settings.settings
@@ -0,0 +1,9 @@
+
+
+
+
+
+ RevitAddInManager
+
+
+
\ No newline at end of file
diff --git a/AddInManager/RelayCommand.cs b/AddInManager/RelayCommand.cs
new file mode 100644
index 0000000..2d68ceb
--- /dev/null
+++ b/AddInManager/RelayCommand.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Windows.Input;
+
+namespace AddInManager
+{
+ internal class RelayCommand : ICommand
+ {
+ private Action