Tiempo de lectura: ~ 6 minutos
959 vistas
Como generar un instalador (.msi) para un plugin de Revit
# Revit API
# Automatización
Actualizado 21 de diciembre de 2024
Una pregunta recurrente en los cursos del cursos Automatización de procesos con la API de Revit es como se puede crear un instalador en formato .msi para un aplicativo creado.
Los multiples tutoriales de inicio siempre nos mencionan que para que un aplicativo creado con la API de Revit sea reconocido por el programa Autodesk Revit es necesario generar una crear un archivo manifiesto (.addin) y un biblioteca de clases (.dll) y estos archivos deben ser copiados en una ruta especifica (C:\Users%User%\AppData\Roaming\Autodesk\Revit\Addins%Version%)que leerá dicho archivo manifiesto.
La solución mas sencilla es crear eventos de compilación que durante el build copie los archivos .dll y .addin en la carpeta mencionada. La otra solución es crear un archivo comprimido auto extraíble con winrar que simplemente extrae los archivos en una ruta especifica. Ver tutorial
copy "$(ProjectDir)*.addin" "$(AppData)\Autodesk\REVIT\Addins\20XX" copy "$(ProjectDir)bin\debug\*.dll" "$(AppData)\Autodesk\REVIT\Addins\20XX"
Dado lo mencionado lo anterior, no convence estas dos soluciones que he venido aplicando es por lo cual investigando me encontré con el tutorial de Joshua Lumley, Revit API C# make Installer MSI File (Executable) ... and avoid my Blunders! (secrets part 2)A, y lo he replicado para una aplicación mas sencilla y claro para la mayoría de mis lectores que manejas ESPANOL
Crear un archivo .msi para un aplicativo con la API de Revit
Lo primero que tenemos que entender es que necesitamos una estructura base minima de tres proyectos para crear un instalador una librería de clases que contendrá el external command o el external aplicación que es nuestro addin de Revit, un proyecto de tipo Setup project que lo obtendremos instalando Microsoft visual studio installer project o la version que función para Visual studio 2022 y por ultimo una librería de clases para el archivo que obtendrá los métodos install y uninstall que ejecutara el proyecto setup.
1. Proyecto de Revit addin
Primero crearemos un proyecto de tipo library class (.Net framework) que llamaremos RevitSimpleCommand en el cual solo crearemos un simple external command que muestre un mensaje a través de un task dialog.
command.cs1using Autodesk.Revit.DB; 2using Autodesk.Revit.UI; 3using Autodesk.Revit.Attributes; 4 5namespace RevitSimpleCommand 6{ 7 [Transaction(TransactionMode.ReadOnly)] 8 public class CmdHelloWorld : IExternalCommand 9 { 10 public Result Execute(ExternalCommandData commandData, 11 ref string message, 12 ElementSet elements) 13 { 14 TaskDialog.Show("Simple title", "Hello World"); 15 return Result.Succeeded; 16 } 17 } 18}
2. Comandos para instalar
En nuestro proyecto creamos un nuevo elemento de tipo installer class que llamaremos InstallerCommands donde solo tendremos dos métodos que servirán para decirle al setup project que secuencia de acciones realizar cuando ejecute el install y un install. Además de los comandos es necesarios instalar dos paquetes de Nuget Extended.Wpf.Toolkit y Ookii.Dialogs.Wpf.
Variables Globales
command.cs1AddinType addinType = AddinType.Command; 2string commandProject = "RevitSimpleCommand"; 3string commandName = "CmdHelloWorld"; 4string companyName = "Lambda Ingenieria e Innovacion"; 5string companyURL = "https://lambda.com.pe/"; 6 7enum AddinType 8 { 9 Command = 0, 10 Application = 1 11 }</Code> 12 13### Metodo Install 14 15<Code language="csharp"> 16public override void Install(IDictionary stateSaver) 17{ 18 Microsoft.Win32.RegistryKey rkbase = null; 19 20 rkbase = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, 21 Microsoft.Win32.RegistryView.Registry64); 22 23 rkbase.CreateSubKey($"SOFTWARE\\Wow6432Node\\{companyName}\\Revit API NuGet Example 2019 Packages", Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree).SetValue("OokiiVersion", typeof(Ookii.Dialogs.Wpf.CredentialDialog).Assembly.FullName); 24 25 rkbase.CreateSubKey($"SOFTWARE\\Wow6432Node\\{companyName}\\Revit API NuGet Example 2019 Packages", 26 Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree).SetValue("XceedVersion", 27 typeof(Xceed.Wpf.Toolkit.PropertyGrid.PropertyGrid).Assembly.FullName); 28 29 string sDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Autodesk\\Revit\\Addins"; 30 bool exists = Directory.Exists(sDir); 31 32 if (!exists) Directory.CreateDirectory(sDir); 33 34 XElement XElementAddIn; 35 if (addinType == AddinType.Command) 36 { 37 XElementAddIn = new XElement("AddIn", new XAttribute("Type", "Command")); 38 XElementAddIn.Add(new XElement("Text", commandProject)); 39 } 40 else { 41 XElementAddIn = new XElement("AddIn", new XAttribute("Type", "Application")); 42 XElementAddIn.Add(new XElement("Name", commandProject)); 43 } 44 45 XElementAddIn.Add(new XElement("Assembly", this.Context.Parameters["targetdir"].Trim() + commandProject + ".dll")); 46 XElementAddIn.Add(new XElement("AddInId", Guid.NewGuid().ToString())); 47 XElementAddIn.Add(new XElement("FullClassName", $"{commandProject}.{commandName}")); 48 XElementAddIn.Add(new XElement("VendorId", "ADSK")); 49 XElementAddIn.Add(new XElement("VendorDescription", $"{companyName}, {companyURL}")); 50 51 XElement XElementRevitAddIns = new XElement("RevitAddIns"); 52 XElementRevitAddIns.Add(XElementAddIn); 53 54 try 55 { 56 foreach (string d in Directory.GetDirectories(sDir)) 57 { 58 new XDocument(XElementRevitAddIns).Save(d + "\\" + commandProject + ".addin"); 59 } 60 } 61 catch (Exception excpt) 62 { 63 MessageBox.Show(excpt.Message); 64 } 65}
Metodo Uninstall
command.cs1public override void Uninstall(IDictionary stateSaver) 2{ 3 string sDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Autodesk\\Revit\\Addins"; 4 5 bool exists = Directory.Exists(sDir); 6 7 Microsoft.Win32.RegistryKey rkbase = null; 8 rkbase = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,Microsoft.Win32.RegistryView.Registry64); 9 rkbase.DeleteSubKeyTree($"SOFTWARE\\Wow6432Node\\${companyName}\\Revit API NuGet Example 2019 Packages"); 10 11 if (exists) 12 { 13 try 14 { 15 foreach (string d in Directory.GetDirectories(sDir)) 16 { 17 File.Delete(d + "\\" + commandProject + ".addin"); 18 } 19 } 20 catch (Exception excpt) 21 { 22 MessageBox.Show(excpt.Message); 23 } 24 } 25}
3. Proyecto Instalador
Lo primero que haremos luego de crear nuestro proyecto que llamaremos RevitAddinInstaller es configurar las propiedades InstallAllUser = true, RemovePreviewVersion = true y TargetPlaform = x64 dentro de la barra de propiedades del proyecto.
Cambiamos los prerrequisitos del proyecto accediendo a las propiedades con una anti clic sobre nuestro proyecto y seleccionados que tipo de .Net framework trabajamos. coloco una imagen para saber que .net framework son compatible según la version de Revit.
Viene la parte mas complicada de nuestro setup project que es configurar para que este proyecto tenga un correcto funcionamiento.
A. Configurar el File System
Para el panel de File System Config es necesario agregar los resultados del build de los proyectos InstallerCommands y RevitSimpleCommand dentro de la carpeta Aplication Folder. Para agregar esta información es necesario entrar el menu desplegable de Aplication folder y seleccionar Resultado de Proyecto. Seleccionamos cada uno de los proyecto y agregamos el Resultado principal.
B. Configurar Register
Para el panel de Register Config es necesario agregar dos variables. ProductVersion y TARGETDIR dentro de la carpeta [ProductName].
1|— 📂HKEY_LOCAL_MACHINE 2 3 |— 📂 Software 4 5 |— 📂 [Manufacturer] 6 7 |— 📂 [ProductName]
Name | Value |
---|---|
ProductVersion | [ProductVersion] |
TARGETDIR | [TARGETDIR] |
C. Configurar Custom Actions Editor
Dentro de las Custom Actions, configuramos las acciones de Install y UnInstall agregando el proyecto InstallerCommands.
Y eso es todo! Es un proceso largo pero creo que con una buena plantilla de proyecto se puede simplificar mucho el proceso. Para los que se perdieron siguiendo los pasos he subido un video a YouTube donde hago un instalador para un complemento de la API de Revit y ya que están por ahí suscríbanse al canal y compártanlo (Me siento el Rubius) para que este tipo de contenido llegue a mas personas.
Suscribirse para recibir actualizaciones
Recibe semanalmente tutoriales, recursos, noticias sobre temas innovadores dentro del sector construcción y destaca profesionalmente.