using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Xml.Linq; using AddinManager.Models; using Newtonsoft.Json; namespace AddinManager.Services { /// /// 插件管理服务 /// public class AddinManagerService { private readonly string _revitVersion; private readonly List _addinFolderPaths; private readonly string _configPath; private readonly Dictionary _loadedAssemblies = new Dictionary(); public AddinManagerService(string revitVersion = null) { _revitVersion = revitVersion ?? DetectCurrentRevitVersion(); _addinFolderPaths = GetAllAddinDirectories(_revitVersion); // 配置文件放在用户目录下 var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Autodesk", "Revit", "Addins", _revitVersion); _configPath = Path.Combine(userAddinPath, "AddinManagerConfig.json"); EnsureDirectoriesExist(); } /// /// 动态检测当前运行的Revit版本 /// private string DetectCurrentRevitVersion() { try { // 方法1:从当前运行的Revit进程检测 var revitProcesses = Process.GetProcessesByName("Revit"); if (revitProcesses.Length > 0) { var process = revitProcesses[0]; var version = ExtractVersionFromProcess(process); if (!string.IsNullOrEmpty(version)) { return version; } } // 方法2:从Revit API获取版本(如果在Revit环境中运行) try { var app = AddinManagerApp.UiApplication.Application; return app.VersionNumber; } catch { // 忽略Revit API获取失败 } // 方法3:从注册表获取最新安装的版本 var installedVersions = GetInstalledRevitVersions(); if (installedVersions.Count > 0) { return installedVersions.OrderByDescending(v => v).First(); } } catch { // 忽略检测失败 } // 默认返回2024版本 return "2024"; } /// /// 从进程信息中提取Revit版本 /// private string ExtractVersionFromProcess(Process process) { try { var fileName = process.MainModule?.FileName; if (!string.IsNullOrEmpty(fileName)) { var directory = Path.GetDirectoryName(fileName); if (directory != null) { // 从路径中提取版本号 for (int year = 2018; year <= 2030; year++) { if (directory.Contains(year.ToString())) { return year.ToString(); } } } // 从文件版本信息中获取 var versionInfo = FileVersionInfo.GetVersionInfo(fileName); if (versionInfo.ProductVersion != null) { var match = System.Text.RegularExpressions.Regex.Match(versionInfo.ProductVersion, @"(\d{4})"); if (match.Success) { return match.Groups[1].Value; } } } } catch { // 忽略错误 } return null; } /// /// 获取系统中安装的所有Revit版本 /// private List GetInstalledRevitVersions() { var versions = new HashSet(); try { // 从注册表获取 using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Autodesk\Revit")) { if (key != null) { foreach (var subKeyName in key.GetSubKeyNames()) { if (int.TryParse(subKeyName, out int year) && year >= 2018 && year <= 2030) { versions.Add(subKeyName); } } } } // 从WOW6432Node获取 using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Autodesk\Revit")) { if (key != null) { foreach (var subKeyName in key.GetSubKeyNames()) { if (int.TryParse(subKeyName, out int year) && year >= 2018 && year <= 2030) { versions.Add(subKeyName); } } } } // 从文件系统检查 var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); foreach (var baseDir in new[] { programFiles, programFilesX86 }) { if (string.IsNullOrEmpty(baseDir)) continue; var autodeskDir = Path.Combine(baseDir, "Autodesk"); if (Directory.Exists(autodeskDir)) { foreach (var dir in Directory.GetDirectories(autodeskDir, "Revit *")) { var dirName = Path.GetFileName(dir); var match = System.Text.RegularExpressions.Regex.Match(dirName, @"Revit (\d{4})"); if (match.Success) { versions.Add(match.Groups[1].Value); } } } } } catch { // 忽略错误 } return versions.ToList(); } /// /// 获取所有可能的插件目录 /// private List GetAllAddinDirectories(string revitVersion) { var directories = new List(); // 1. 用户级插件目录 (当前用户) - .addin文件 var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Autodesk", "Revit", "Addins", revitVersion); directories.Add(userAddinPath); // 2. 用户级ApplicationPlugins目录 - .bundle文件夹 var userAppPluginsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Autodesk", "ApplicationPlugins"); directories.Add(userAppPluginsPath); // 3. 全局插件目录 (所有用户) - .addin文件 var globalAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Autodesk", "Revit", "Addins", revitVersion); directories.Add(globalAddinPath); // 4. 全局ApplicationPlugins目录 - .bundle文件夹 var globalAppPluginsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Autodesk", "ApplicationPlugins"); directories.Add(globalAppPluginsPath); // 5. 程序文件目录下的通用插件目录 var programFilesAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Autodesk", $"Revit {revitVersion}", "AddIns"); if (Directory.Exists(programFilesAddinPath)) { directories.Add(programFilesAddinPath); } // 6. 程序文件(x86)目录下的插件目录 var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); if (!string.IsNullOrEmpty(programFilesX86)) { var programFilesX86AddinPath = Path.Combine(programFilesX86, "Autodesk", $"Revit {revitVersion}", "AddIns"); if (Directory.Exists(programFilesX86AddinPath)) { directories.Add(programFilesX86AddinPath); } } // 去重并返回存在的目录 return directories.Distinct().Where(Directory.Exists).ToList(); } /// /// 获取Revit的安装路径 /// private List GetRevitInstallPaths(string revitVersion) { var installPaths = new List(); try { // 从注册表查找Revit安装路径 using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey($@"SOFTWARE\Autodesk\Revit\{revitVersion}")) { if (key != null) { var installPath = key.GetValue("InstallationPath") as string; if (!string.IsNullOrEmpty(installPath) && Directory.Exists(installPath)) { installPaths.Add(installPath); } } } // 从注册表查找其他可能的路径 (WOW6432Node for 32-bit apps on 64-bit Windows) using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey($@"SOFTWARE\WOW6432Node\Autodesk\Revit\{revitVersion}")) { if (key != null) { var installPath = key.GetValue("InstallationPath") as string; if (!string.IsNullOrEmpty(installPath) && Directory.Exists(installPath)) { installPaths.Add(installPath); } } } } catch { // 忽略注册表读取错误 } // 如果注册表查找失败,尝试常见的安装路径 var commonPaths = new[] { Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Autodesk", $"Revit {revitVersion}"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Autodesk", $"Revit {revitVersion}"), Path.Combine("C:", "Program Files", "Autodesk", $"Revit {revitVersion}"), Path.Combine("C:", "Program Files (x86)", "Autodesk", $"Revit {revitVersion}") }; foreach (var path in commonPaths) { if (Directory.Exists(path)) { installPaths.Add(path); } } return installPaths.Distinct().ToList(); } /// /// 获取所有已安装的插件(包括已禁用的和Bundle格式的) /// public List GetInstalledAddins() { var addins = new List(); // 扫描所有插件目录 foreach (var addinFolderPath in _addinFolderPaths) { if (!Directory.Exists(addinFolderPath)) continue; try { // 检查是否是ApplicationPlugins目录(Bundle格式) if (addinFolderPath.Contains("ApplicationPlugins")) { // 扫描Bundle格式插件 var bundleAddins = ScanBundlePlugins(addinFolderPath); addins.AddRange(bundleAddins); } else { // 扫描传统.addin文件格式 var traditionalAddins = ScanTraditionalAddins(addinFolderPath); addins.AddRange(traditionalAddins); } } catch (Exception ex) { // 记录目录访问错误 var errorAddin = new AddinInfo { Name = $"目录访问错误: {Path.GetFileName(addinFolderPath)}", AddinFilePath = addinFolderPath, SourceDirectory = addinFolderPath, HasErrors = true, ErrorMessages = new List { $"无法访问目录: {ex.Message}" }, Status = "访问错误", IsEnabled = false }; addins.Add(errorAddin); } } return addins; } /// /// 扫描传统.addin文件格式的插件 /// private List ScanTraditionalAddins(string addinFolderPath) { var addins = new List(); // 扫描所有.addin文件(包括.disabled文件) var addinFiles = Directory.GetFiles(addinFolderPath, "*.addin", SearchOption.AllDirectories) .Concat(Directory.GetFiles(addinFolderPath, "*.addin.disabled", SearchOption.AllDirectories)) .ToArray(); foreach (var addinFile in addinFiles) { try { var addinInfos = ParseAddinFile(addinFile); foreach (var addinInfo in addinInfos) { // 标记插件来源目录 addinInfo.SourceDirectory = addinFolderPath; addins.Add(addinInfo); } } catch (Exception ex) { // 记录解析错误 var errorAddin = new AddinInfo { Name = Path.GetFileNameWithoutExtension(addinFile), AddinFilePath = addinFile, SourceDirectory = addinFolderPath, HasErrors = true, ErrorMessages = new List { ex.Message }, Status = "解析错误", IsEnabled = false }; addins.Add(errorAddin); } } return addins; } /// /// 扫描Bundle格式的插件(.bundle文件夹) /// private List ScanBundlePlugins(string appPluginsPath) { var addins = new List(); // 查找所有.bundle文件夹 var bundleFolders = Directory.GetDirectories(appPluginsPath, "*.bundle", SearchOption.TopDirectoryOnly); foreach (var bundleFolder in bundleFolders) { try { // 查找PackageContents.xml文件 var packageContentsPath = Path.Combine(bundleFolder, "PackageContents.xml"); if (File.Exists(packageContentsPath)) { var bundleAddins = ParseBundlePackage(packageContentsPath, bundleFolder); addins.AddRange(bundleAddins); } else { // 如果没有PackageContents.xml,记录为错误 var errorAddin = new AddinInfo { Name = Path.GetFileNameWithoutExtension(bundleFolder), AddinFilePath = bundleFolder, SourceDirectory = appPluginsPath, HasErrors = true, ErrorMessages = new List { "Bundle文件夹中缺少PackageContents.xml文件" }, Status = "Bundle格式错误", IsEnabled = false }; addins.Add(errorAddin); } } catch (Exception ex) { // 记录Bundle解析错误 var errorAddin = new AddinInfo { Name = Path.GetFileNameWithoutExtension(bundleFolder), AddinFilePath = bundleFolder, SourceDirectory = appPluginsPath, HasErrors = true, ErrorMessages = new List { $"Bundle解析错误: {ex.Message}" }, Status = "Bundle解析错误", IsEnabled = false }; addins.Add(errorAddin); } } return addins; } /// /// 解析Bundle格式的PackageContents.xml文件 /// private List ParseBundlePackage(string packageContentsPath, string bundleFolder) { var addins = new List(); var doc = XDocument.Load(packageContentsPath); // 获取Bundle的基本信息 var packageElement = doc.Element("ApplicationPackage"); if (packageElement == null) return addins; var bundleName = packageElement.Attribute("Name")?.Value ?? Path.GetFileNameWithoutExtension(bundleFolder); var bundleVersion = packageElement.Attribute("Version")?.Value ?? "Unknown"; var bundleDescription = packageElement.Attribute("Description")?.Value ?? ""; var bundleAuthor = packageElement.Attribute("Author")?.Value ?? "Unknown"; // 查找支持的Revit版本 var supportedVersions = new List(); var componentsElement = packageElement.Element("Components"); if (componentsElement != null) { foreach (var runtimeRequirements in componentsElement.Descendants("RuntimeRequirements")) { var platform = runtimeRequirements.Attribute("Platform")?.Value; var version = runtimeRequirements.Attribute("Version")?.Value; if (platform == "Revit" && !string.IsNullOrEmpty(version)) { supportedVersions.Add(version); } } } // 查找所有的AddIn元素 foreach (var componentElement in componentsElement?.Elements("ComponentEntry") ?? Enumerable.Empty()) { var moduleType = componentElement.Attribute("ModuleType")?.Value; if (moduleType != "Managed") continue; // 只处理托管代码插件 var appName = componentElement.Attribute("AppName")?.Value ?? bundleName; var appDescription = componentElement.Attribute("AppDescription")?.Value ?? bundleDescription; // 检查是否被禁用(通过重命名bundle文件夹) bool isDisabled = bundleFolder.EndsWith(".bundle.disabled") || bundleFolder.EndsWith(".disabled"); var addin = new AddinInfo { Name = appName, Description = appDescription, Version = bundleVersion, Developer = bundleAuthor, AddinFilePath = packageContentsPath, SourceDirectory = Path.GetDirectoryName(bundleFolder), Type = AddinType.Application, // Bundle通常是Application类型 CurrentRevitVersion = _revitVersion, LastModified = File.GetLastWriteTime(packageContentsPath), IsEnabled = !isDisabled, Status = isDisabled ? "已禁用" : "已启用" }; // 添加支持的版本 foreach (var version in supportedVersions) { addin.SupportedRevitVersions.Add(version); } // 查找程序集路径 var appModule = componentElement.Element("AppModule"); if (appModule != null) { var relativePath = appModule.Value; if (!string.IsNullOrEmpty(relativePath)) { var assemblyPath = Path.Combine(bundleFolder, "Contents", relativePath); addin.AssemblyPath = assemblyPath; // 尝试获取程序集版本信息 if (File.Exists(assemblyPath)) { try { var assembly = Assembly.LoadFrom(assemblyPath); var assemblyVersion = assembly.GetName().Version?.ToString(); if (!string.IsNullOrEmpty(assemblyVersion)) { addin.Version = assemblyVersion; } // 查找主类 var types = assembly.GetTypes(); var appType = types.FirstOrDefault(t => t.GetInterfaces() .Any(i => i.Name.Contains("IExternalApplication"))); if (appType != null) { addin.ClassName = appType.FullName; } } catch { // 忽略程序集加载错误 } } } } addins.Add(addin); } return addins; } /// /// 启用插件 - 支持传统.addin文件和Bundle格式 /// public bool EnableAddin(AddinInfo addin) { try { // 检查是否是Bundle格式插件 if (IsBundlePlugin(addin)) { return EnableBundlePlugin(addin); } else { return EnableTraditionalPlugin(addin); } } catch (Exception ex) { addin.ErrorMessages.Add($"启用失败: {ex.Message}"); return false; } } /// /// 禁用插件 - 支持传统.addin文件和Bundle格式 /// public bool DisableAddin(AddinInfo addin) { try { // 检查是否是Bundle格式插件 if (IsBundlePlugin(addin)) { return DisableBundlePlugin(addin); } else { return DisableTraditionalPlugin(addin); } } catch (Exception ex) { addin.ErrorMessages.Add($"禁用失败: {ex.Message}"); return false; } } /// /// 检查是否是Bundle格式插件 /// private bool IsBundlePlugin(AddinInfo addin) { return addin.AddinFilePath.Contains("ApplicationPlugins") && addin.AddinFilePath.EndsWith("PackageContents.xml"); } /// /// 启用传统.addin文件格式插件 /// private bool EnableTraditionalPlugin(AddinInfo addin) { if (!File.Exists(addin.AddinFilePath)) return false; // 如果文件以.disabled结尾,重命名回.addin if (addin.AddinFilePath.EndsWith(".disabled")) { string enabledPath = addin.AddinFilePath.Replace(".addin.disabled", ".addin"); File.Move(addin.AddinFilePath, enabledPath); addin.AddinFilePath = enabledPath; } addin.IsEnabled = true; SaveAddinState(addin); return true; } /// /// 禁用传统.addin文件格式插件 /// private bool DisableTraditionalPlugin(AddinInfo addin) { if (!File.Exists(addin.AddinFilePath)) return false; // 如果文件以.addin结尾,重命名为.addin.disabled if (addin.AddinFilePath.EndsWith(".addin")) { string disabledPath = addin.AddinFilePath + ".disabled"; File.Move(addin.AddinFilePath, disabledPath); addin.AddinFilePath = disabledPath; } addin.IsEnabled = false; SaveAddinState(addin); return true; } /// /// 启用Bundle格式插件 /// private bool EnableBundlePlugin(AddinInfo addin) { var bundleFolder = Path.GetDirectoryName(addin.AddinFilePath); if (!Directory.Exists(bundleFolder)) return false; // 如果Bundle文件夹以.disabled结尾,重命名回.bundle if (bundleFolder.EndsWith(".disabled")) { string enabledPath = bundleFolder.Replace(".bundle.disabled", ".bundle"); Directory.Move(bundleFolder, enabledPath); // 更新插件信息中的路径 addin.AddinFilePath = Path.Combine(enabledPath, "PackageContents.xml"); addin.SourceDirectory = Path.GetDirectoryName(enabledPath); } else if (bundleFolder.EndsWith(".bundle.disabled")) { string enabledPath = bundleFolder.Replace(".bundle.disabled", ".bundle"); Directory.Move(bundleFolder, enabledPath); // 更新插件信息中的路径 addin.AddinFilePath = Path.Combine(enabledPath, "PackageContents.xml"); addin.SourceDirectory = Path.GetDirectoryName(enabledPath); } addin.IsEnabled = true; SaveAddinState(addin); return true; } /// /// 禁用Bundle格式插件 /// private bool DisableBundlePlugin(AddinInfo addin) { var bundleFolder = Path.GetDirectoryName(addin.AddinFilePath); if (!Directory.Exists(bundleFolder)) return false; // 如果Bundle文件夹以.bundle结尾,重命名为.bundle.disabled if (bundleFolder.EndsWith(".bundle")) { string disabledPath = bundleFolder + ".disabled"; Directory.Move(bundleFolder, disabledPath); // 更新插件信息中的路径 addin.AddinFilePath = Path.Combine(disabledPath, "PackageContents.xml"); addin.SourceDirectory = Path.GetDirectoryName(disabledPath); } addin.IsEnabled = false; SaveAddinState(addin); return true; } /// /// 卸载插件 /// public bool UninstallAddin(AddinInfo addin) { try { // 删除.addin文件 if (File.Exists(addin.AddinFilePath)) { File.Delete(addin.AddinFilePath); } // 删除程序集文件(如果在插件目录下) if (File.Exists(addin.AssemblyPath) && _addinFolderPaths.Any(path => addin.AssemblyPath.StartsWith(path))) { File.Delete(addin.AssemblyPath); } RemoveAddinState(addin); return true; } catch (Exception ex) { addin.ErrorMessages.Add($"卸载失败: {ex.Message}"); return false; } } /// /// 热重载插件 - 增强版本 /// public bool HotReloadAddin(AddinInfo addin) { try { // 先禁用插件 if (addin.IsEnabled) { DisableAddin(addin); } // 卸载已加载的程序集 if (_loadedAssemblies.ContainsKey(addin.AssemblyPath)) { _loadedAssemblies.Remove(addin.AssemblyPath); } // 等待一段时间确保���件释放 System.Threading.Thread.Sleep(500); // 重新启用插件 EnableAddin(addin); addin.LastModified = File.GetLastWriteTime(addin.AssemblyPath); return true; } catch (Exception ex) { addin.ErrorMessages.Add($"热重载失败: {ex.Message}"); return false; } } /// /// 安装插件 /// public bool InstallAddin(string addinFilePath, string targetDirectory = null) { try { if (targetDirectory == null) { // 默认安装到用户插件目录(第一个目录) targetDirectory = _addinFolderPaths.FirstOrDefault() ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Autodesk", "Revit", "Addins", _revitVersion); } var fileName = Path.GetFileName(addinFilePath); var targetPath = Path.Combine(targetDirectory, fileName); File.Copy(addinFilePath, targetPath, true); return true; } catch (Exception) { return false; } } /// /// 检查插件兼容性 /// public bool CheckCompatibility(AddinInfo addin) { return addin.SupportedRevitVersions.Contains(_revitVersion) || addin.SupportedRevitVersions.Count == 0; } /// /// 获取插件错误日志 /// public List GetAddinErrors(AddinInfo addin) { return addin.ErrorMessages; } /// /// 安装临时调试插件 - 直接加载到Revit中 /// public bool InstallTemporaryDebugAddin(CommandInfo commandInfo, string commandName) { try { #if REVIT_API_AVAILABLE // 直接通过Revit API加载插件 var uiApp = AddinManagerApp.UiApplication; if (uiApp == null) { System.Diagnostics.Debug.WriteLine("Revit应用程序未初始化"); return false; } // 加载程序集 var assembly = Assembly.LoadFrom(commandInfo.AssemblyPath); var commandType = assembly.GetType(commandInfo.ClassName); if (commandType == null) { System.Diagnostics.Debug.WriteLine($"无法找到类型: {commandInfo.ClassName}"); return false; } // 创建外部命令数据 var commandData = new Autodesk.Revit.UI.ExternalCommandData(); // 将命令添加到临时调试命令列表 var tempCommandId = $"DebugCmd_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid().ToString("N")[..8]}"; // 创建临时按钮(可选,用于UI访问) try { var ribbonTab = uiApp.GetRibbonTabs().FirstOrDefault(t => t == "调试") ?? uiApp.CreateRibbonTab("调试"); var panel = uiApp.GetRibbonPanels("调试").FirstOrDefault(p => p.Name == "临时命令") ?? uiApp.CreateRibbonPanel("调试", "临时命令"); var buttonData = new Autodesk.Revit.UI.PushButtonData( tempCommandId, commandName, commandInfo.AssemblyPath, commandInfo.ClassName); var button = panel.AddItem(buttonData) as Autodesk.Revit.UI.PushButton; if (button != null) { button.ToolTip = $"临时调试命令: {commandName}"; button.LongDescription = $"从 {Path.GetFileName(commandInfo.AssemblyPath)} 加载的调试命令"; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"创建临时按钮失败: {ex.Message}"); // 即使按钮创建失败,命令仍然可以通过其他方式调用 } // 记录已加载的临时命令 if (!_loadedAssemblies.ContainsKey(commandInfo.AssemblyPath)) { _loadedAssemblies.Add(commandInfo.AssemblyPath, assembly); } return true; #else // 在没有Revit API的环境中,仍然创建.addin文件作为fallback return CreateTemporaryAddinFile(commandInfo, commandName); #endif } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"直接加载插件失败: {ex.Message}"); return false; } } /// /// 创建临时.addin文件作为备用方案 /// private bool CreateTemporaryAddinFile(CommandInfo commandInfo, string commandName) { try { // 确保用户插件目录存在 var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Autodesk", "Revit", "Addins", _revitVersion); if (!Directory.Exists(userAddinPath)) { Directory.CreateDirectory(userAddinPath); } // 生成临时插件的唯一标识 var tempAddinId = $"DebugAddin_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid().ToString("N")[..8]}"; var tempAddinFileName = $"{tempAddinId}.addin"; var tempAddinFilePath = Path.Combine(userAddinPath, tempAddinFileName); // 创建临时.addin文件内容 var addinXml = CreateDebugAddinXml(commandInfo, commandName, tempAddinId); // 写入.addin文件 File.WriteAllText(tempAddinFilePath, addinXml); return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"创建临时addin文件失败: {ex.Message}"); return false; } } /// /// 直接执行命令(用于调试测试) /// public bool ExecuteCommand(CommandInfo commandInfo) { try { #if REVIT_API_AVAILABLE var uiApp = AddinManagerApp.UiApplication; if (uiApp == null) return false; // 加载程序集 var assembly = Assembly.LoadFrom(commandInfo.AssemblyPath); var commandType = assembly.GetType(commandInfo.ClassName); if (commandType == null) return false; // 创建命令实例 var commandInstance = Activator.CreateInstance(commandType) as Autodesk.Revit.UI.IExternalCommand; if (commandInstance == null) return false; // 准备命令数据 var commandData = new Autodesk.Revit.UI.ExternalCommandData { Application = uiApp, JournalData = new Autodesk.Revit.DB.NameValueMap() }; var message = string.Empty; var elementSet = new Autodesk.Revit.DB.ElementSet(); // 执行命令 var result = commandInstance.Execute(commandData, ref message, elementSet); return result == Autodesk.Revit.UI.Result.Succeeded; #else return false; #endif } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"执行命令失败: {ex.Message}"); return false; } } /// /// 卸载临时调试插件 /// public bool UnloadTemporaryDebugAddin(string assemblyPath) { try { // 从已加载程序集列表中移除 if (_loadedAssemblies.ContainsKey(assemblyPath)) { _loadedAssemblies.Remove(assemblyPath); } // 释放程序集引用 ReleaseDllReferences(); return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"卸载临时插件失败: {ex.Message}"); return false; } } /// /// 创建调试插件的XML内容 /// private string CreateDebugAddinXml(CommandInfo commandInfo, string commandName, string addinId) { var xml = $@" {commandName} {commandInfo.AssemblyPath} {commandInfo.ClassName} 临时调试插件 - {commandName} AddinManager.Debug Revit插件管理器调试功能 {_revitVersion} {commandInfo.TransactionMode} "; return xml; } /// /// 从DLL中获取命令信息 /// public List GetCommandsFromDll(string dllPath) { var commands = new List(); try { if (!File.Exists(dllPath)) { return commands; } // 加载程序集 var assembly = Assembly.LoadFrom(dllPath); // 查找实现IExternalCommand接口的类 foreach (var type in assembly.GetTypes()) { if (type.IsClass && !type.IsAbstract) { // 检查是否实现了IExternalCommand接口 var interfaces = type.GetInterfaces(); bool implementsIExternalCommand = false; foreach (var interfaceType in interfaces) { if (interfaceType.Name == "IExternalCommand" || interfaceType.FullName?.Contains("IExternalCommand") == true) { implementsIExternalCommand = true; break; } } if (implementsIExternalCommand) { var commandInfo = new CommandInfo { ClassName = type.FullName, AssemblyPath = dllPath, Assembly = assembly, Type = type, TransactionMode = GetTransactionMode(type) }; commands.Add(commandInfo); } } } } catch (Exception ex) { // 返回错误信息 var errorCommand = new CommandInfo { ClassName = "Error", AssemblyPath = dllPath, HasErrors = true, ErrorMessage = ex.Message }; commands.Add(errorCommand); } return commands; } /// /// 获取命令的事务模式 /// private string GetTransactionMode(Type type) { try { // 查找Transaction特性 var transactionAttribute = type.GetCustomAttributes(false) .FirstOrDefault(attr => attr.GetType().Name.Contains("Transaction")); if (transactionAttribute != null) { // 尝试获取事务模式值 var modeProperty = transactionAttribute.GetType().GetProperty("Mode"); if (modeProperty != null) { var modeValue = modeProperty.GetValue(transactionAttribute); return modeValue?.ToString() ?? "Manual"; } } return "Manual"; // 默认事务模式 } catch { return "Manual"; } } /// /// 附加到Revit进程进行调试 /// public bool AttachToRevitProcess() { try { var revitProcesses = Process.GetProcessesByName("Revit"); if (revitProcesses.Length == 0) { return false; } // 如果有多个Revit进程,选择第一个 var revitProcess = revitProcesses[0]; var processId = revitProcess.Id; // 尝试启动Visual Studio并附加到进程 var vsInstances = GetVisualStudioInstances(); if (vsInstances.Count > 0) { var vsPath = vsInstances.First(); var startInfo = new ProcessStartInfo { FileName = vsPath, Arguments = $"/debugexe", UseShellExecute = true }; Process.Start(startInfo); return true; } return false; } catch { return false; } } /// /// 获取已安装的Visual Studio实例 /// private List GetVisualStudioInstances() { var instances = new List(); try { // 查找Visual Studio的常见安装路径 var possiblePaths = new[] { @"Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.exe", @"Microsoft Visual Studio\2022\Professional\Common7\IDE\devenv.exe", @"Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe", @"Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe", @"Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.exe", @"Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe" }; var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); foreach (var basePath in new[] { programFiles, programFilesX86 }) { if (string.IsNullOrEmpty(basePath)) continue; foreach (var relativePath in possiblePaths) { var fullPath = Path.Combine(basePath, relativePath); if (File.Exists(fullPath)) { instances.Add(fullPath); } } } } catch { // 忽略错误 } return instances; } /// /// 清理临时调试插件 /// public void CleanupTemporaryDebugAddins() { try { var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Autodesk", "Revit", "Addins", _revitVersion); if (!Directory.Exists(userAddinPath)) return; // 查找所有临时调试插件文件 var tempFiles = Directory.GetFiles(userAddinPath, "DebugAddin_*.addin"); foreach (var tempFile in tempFiles) { try { // 检查文件是否超过1天,如果是则删除 var fileInfo = new FileInfo(tempFile); if (DateTime.Now - fileInfo.CreationTime > TimeSpan.FromDays(1)) { File.Delete(tempFile); } } catch { // 忽略单个文件删除失败 } } } catch { // 忽略清理错误 } } /// /// 释放程序集引用以便重新编译 /// public void ReleaseDllReferences() { try { _loadedAssemblies.Clear(); // 强制垃圾回收 GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } catch { // 忽略错误 } } private void EnsureDirectoriesExist() { foreach (var directory in _addinFolderPaths) { if (!Directory.Exists(directory)) { try { Directory.CreateDirectory(directory); } catch { // 忽略创建目录失败 } } } } private void SaveAddinState(AddinInfo addin) { try { var states = new Dictionary(); if (File.Exists(_configPath)) { var json = File.ReadAllText(_configPath); states = JsonConvert.DeserializeObject>(json) ?? new Dictionary(); } var key = $"{addin.ClassName}|{Path.GetFileNameWithoutExtension(addin.AddinFilePath)}"; states[key] = addin.IsEnabled; var updatedJson = JsonConvert.SerializeObject(states, Formatting.Indented); File.WriteAllText(_configPath, updatedJson); } catch { // 忽略保存错误 } } private void RemoveAddinState(AddinInfo addin) { try { if (!File.Exists(_configPath)) return; var json = File.ReadAllText(_configPath); var states = JsonConvert.DeserializeObject>(json); if (states != null) { var key = $"{addin.ClassName}|{Path.GetFileNameWithoutExtension(addin.AddinFilePath)}"; if (states.ContainsKey(key)) { states.Remove(key); var updatedJson = JsonConvert.SerializeObject(states, Formatting.Indented); File.WriteAllText(_configPath, updatedJson); } } } catch { // 忽略错误 } } /// /// 解析.addin文件 /// private List ParseAddinFile(string addinFilePath) { var addins = new List(); var doc = XDocument.Load(addinFilePath); // 判断文件是否被禁用(通过文件扩展名) bool isDisabled = addinFilePath.EndsWith(".disabled"); foreach (var addinElement in doc.Descendants("AddIn")) { var addin = new AddinInfo { AddinFilePath = addinFilePath, CurrentRevitVersion = _revitVersion, LastModified = File.GetLastWriteTime(addinFilePath), IsEnabled = !isDisabled }; // 解析类型 var typeAttr = addinElement.Attribute("Type")?.Value; switch (typeAttr) { case "Command": addin.Type = AddinType.Command; break; case "Application": addin.Type = AddinType.Application; break; case "ExternalDBApplication": addin.Type = AddinType.ExternalDBApplication; break; default: addin.Type = AddinType.Unknown; break; } addin.Name = addinElement.Element("Name")?.Value ?? "Unknown"; addin.Description = addinElement.Element("Description")?.Value ?? ""; addin.AssemblyPath = addinElement.Element("Assembly")?.Value ?? ""; addin.ClassName = addinElement.Element("FullClassName")?.Value ?? ""; addin.Developer = addinElement.Element("VendorId")?.Value ?? "Unknown"; // 解析版本兼容性 var versionElements = addinElement.Elements("SupportedVersion"); foreach (var versionElement in versionElements) { addin.SupportedRevitVersions.Add(versionElement.Value); } // 如果程序集路径是相对路径,转换为绝对路径 if (!Path.IsPathRooted(addin.AssemblyPath)) { addin.AssemblyPath = Path.Combine(Path.GetDirectoryName(addinFilePath), addin.AssemblyPath); } // 尝试获取程序集版本信息 if (File.Exists(addin.AssemblyPath)) { try { var assembly = Assembly.LoadFrom(addin.AssemblyPath); addin.Version = assembly.GetName().Version?.ToString() ?? "Unknown"; } catch { addin.Version = "Unknown"; } } addins.Add(addin); } return addins; } /// /// 获取正在运行的Revit进程 /// public List GetRevitProcesses() { var processes = new List(); try { var revitProcesses = Process.GetProcessesByName("Revit"); foreach (var process in revitProcesses) { try { var processInfo = new ProcessInfo { Id = process.Id, ProcessName = process.ProcessName, WindowTitle = process.MainWindowTitle, StartTime = process.StartTime }; processes.Add(processInfo); } catch { // 忽略无法访问的进程 } } } catch { // 忽略获取进程失败 } return processes; } /// /// 清理调试插件 /// public void CleanupDebugAddins() { try { // 清理临时调试文件 CleanupTemporaryDebugAddins(); // 释放程序集引用 ReleaseDllReferences(); System.Diagnostics.Debug.WriteLine("调试插件清理完成"); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"清理调试插件失败: {ex.Message}"); } } } /// /// 进程信息模型 /// public class ProcessInfo { public int Id { get; set; } public string ProcessName { get; set; } public string WindowTitle { get; set; } public DateTime StartTime { get; set; } } }