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; }
}
}