Quandu si sviluppanu plug-in per applicazioni CAD (
Quandu avete solu un plugin o sì sempre un principiante autodidatta in questu affari, pudete simpricimenti fà una copia di u prugettu, cambià i posti necessarii in questu è custruisce una nova versione di u plugin. In cunsiquenza, i cambiamenti successivi à u codice implicanu un aumentu multiple di i costi di u travagliu.
Cume avete acquistatu sperienza è cunniscenze, truverete parechje manere di automatizà stu prucessu. Sò andatu in questu modu è vogliu dì ciò chì aghju finitu è quantu hè convenientu.
Prima, fighjemu un metudu chì hè evidenti è chì aghju utilizatu per un bellu pezzu
Ligami à i schedari di prughjettu
È per fà tuttu simplice, chjaru è comprensibile, descriveraghju tuttu cù un esempiu astrattu di sviluppu di plugin.
Apertemu Visual Studio (aghju a versione Community 2019. E sì - in russo) è creanu una nova suluzione. Chjamemu MySuperPluginForRevit
Faremu un plugin per Revit per e versioni 2015-2020. Per quessa, aghju da creà un novu prughjettu in a suluzione (Net Framework Class Library) è chjamà MySuperPluginForRevit_2015
Avemu bisognu di aghjunghje referenze à l'API Revit. Di sicuru, pudemu aghjunghje ligami à i fugliali lucali (avete bisognu di installà tutti i SDK necessarii o tutte e versioni di Revit), ma andemu drittu avanti è includenu u pacchettu NuGet. Pudete truvà uni pochi di pacchetti, ma aghju aduprà u mo propiu.
Dopu avè cunnessu u pacchettu, fate un clic right nantu à l'elementu "referenze' è selezziunate l'elementu di menu 'Sposta packages.config à PackageReference...»
Sè di colpu cuminciate à panicu in questu locu, postu chì ùn ci sarà micca un articulu impurtante in a finestra di e proprietà di u pacchettu "copia in u locu", chì avemu definitu bisognu di stabilisce sbagliate, Tandu ùn panicu - andate à u cartulare di u prughjettu, apre u schedariu cù l'estensione .csproj in un editore cunvene per voi (aghju utilizatu Notepad ++) è truvate una entrata nantu à u nostru pacchettu quì. Avà pare cusì:
<PackageReference Include="ModPlus.Revit.API.2015">
<Version>1.0.0</Version>
</PackageReference>
Aghjunghjendu una prupietà à questu runtime. Risultarà cusì:
<PackageReference Include="ModPlus.Revit.API.2015">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
Avà, quandu custruisce un prughjettu, i schedari da u pacchettu ùn sarà micca copiatu à u cartulare di pruduzzioni.
Andemu avanti - imagine solu chì u nostru plugin aduprà qualcosa da l'API Revit, chì hà cambiatu cù u tempu cù a liberazione di novi versioni. Eppo, o avemu solu bisognu di cambià qualcosa di u nostru propiu in u codice, secondu a versione di Revit per quale facemu u plugin. Per risolve tali diffirenzii in u codice, usemu simboli di compilazione cundiziunali. Aprite e proprietà di u prughjettu, andate à a tabulazione "Assemblea"è in u campu"Notazione di compilazione cundizionale» scrivite R2015.
Nota chì u simbulu deve esse aghjuntu sia per a cunfigurazione Debug sia per a cunfigurazione Release.
Ebbè, mentre simu in a finestra di e proprietà, andemu immediatamente à a tabulazione "Applicazione"è in u campu"Spaziu di nomi predeterminatu» caccià u suffissu _2015cusì chì u nostru spaziu di nome hè universale è indipendente da u nome di l'assemblea:
In u mo casu, in u pruduttu finali, i plugins di tutte e versioni sò aghjuntu à un cartulare, cusì i mo nomi di assemblea restanu cù u suffissu di a forma. _20xx. Ma pudete ancu caccià u suffissu da u nome di l'assemblea s'è vo aspettate chì i schedari si trovanu in diversi cartulare.
Andemu à u codice di u schedariu Class1.cs è simulate qualchì codice quì, tenendu in contu e diverse versioni di Revit:
namespace MySuperPluginForRevit
{
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
[Regeneration(RegenerationOption.Manual)]
[Transaction(TransactionMode.Manual)]
public class Class1 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
#if R2015
TaskDialog.Show("ModPlus", "Hello Revit 2015");
#elif R2016
TaskDialog.Show("ModPlus", "Hello Revit 2016");
#elif R2017
TaskDialog.Show("ModPlus", "Hello Revit 2017");
#elif R2018
TaskDialog.Show("ModPlus", "Hello Revit 2018");
#elif R2019
TaskDialog.Show("ModPlus", "Hello Revit 2019");
#elif R2020
TaskDialog.Show("ModPlus", "Hello Revit 2020");
#endif
return Result.Succeeded;
}
}
}
Immediatamente aghju pigliatu in contu tutte e versioni di Revit sopra à a versione 2015 (chì eranu à u mumentu di a scrittura di l'articulu) è hà pigliatu subitu in contu a presenza di simboli di compilazione cundizionale chì creanu secondu u listessu mudellu.
Passemu à u puntu principale. Creemu un novu prughjettu in a nostra suluzione, solu per a versione plug-in sottu Revit 2016. Ripetimu tutti i passi descritti sopra, rispettivamente, rimpiazzà u numeru 2015 cù u numeru 2016. Ma u schedariu. Class1.cs cacciatu da u novu prughjettu.
File cù u codice necessariu - Class1.cs - avemu digià è avemu solu bisognu di inserisce un ligame in un novu prughjettu. Ci hè dui modi per inserisce ligami:
- Longu - cliccate nant'à u prugettu cù u buttone drittu di u mouse, selezziunate l'elementu "Ajouter»->«Elementu esistenti", in a finestra chì si apre, truvate u schedariu desideratu è invece di l'opzione"Ajouter» sceglite l'opzione «Aghjunghjite cum'è ligame»
- Cortu - ghjustu in l'esploratore di suluzione, selezziunate u schedariu desideratu (o ancu i fugliali. O ancu i cartulare interi) è trascinallu in un novu prughjettu mentre mantene a chjave Alt. Quandu trascinate, vi vede chì quandu pressu a chjave Alt, u cursore nantu à u mouse cambierà da un segnu più à una freccia.
UPS: Aghju fattu un pocu cunfusione in questu paràgrafu - per trasfiriri parechji schedari, duvete clamp Shift + Alt!
Dopu à a prucedura, avemu un schedariu in u secondu prughjettu Class1.cs cù l'icona corrispondente (freccia blu):
Quandu editate u codice in a finestra di l'editore, pudete ancu sceglie in u cuntestu di quale prughjettu per vede u codice, chì vi permetterà di vede u codice editatu cù diversi simboli di compilazione cundizionale:
Sicondu stu schema, creamu tutti l'altri prughjetti (2017-2020). Hack di vita - se trascinate i fugliali in l'esploratore di suluzione micca da u prugettu di basa, ma da u prughjettu induve sò digià inseriti cum'è un ligame, allora ùn pudete micca mantene a chjave Alt!
L'opzione descritta hè abbastanza bona finu à chì una nova versione di u plugin hè aghjuntu o finu à chì i novi schedari sò aghjuntu à u prugettu - tuttu questu diventa assai triste. È pocu tempu, aghju capitu di colpu cumu per sorte tuttu cù un prughjettu è andemu à u sicondu metudu.
Magia di cunfigurazione
Dopu avè lettu quì, pudete esclamà: "Chì diavolo avete descrittu u primu metudu, se l'articulu hè subitu nantu à u sicondu ?!". E aghju descrittu tuttu per fà più chjaru perchè avemu bisognu di simboli di compilazione cundizionale è in quali posti i nostri prughjetti sò diffirenti. È avà diventa più chjaru per noi chì tipu di differenzi di prughjettu avemu bisognu di implementà, lascendu solu un prughjettu.
È per fà tuttu più evidenti, ùn avemu micca creatu un novu prughjettu, ma faremu cambiamenti à u nostru prughjettu attuale creatu in u primu modu.
Allora, prima di tuttu, sguassate tutti i prughjetti da a suluzione, fora di u principale (cuntenendu i schedarii direttamente). Quelli. prughjetti per e versioni 2016-2020. Aprite u cartulare cù a suluzione è sguassà i cartulare di sti prughjetti ci.
Avemu un prughjettu lasciatu in a suluzione - MySuperPluginForRevit_2015. Aprite e so proprietà è:
- In a tabulazione "Applicazione» caccià u suffissu da u nome di l'assemblea _2015 (sarà chjaru perchè dopu)
- In a tabulazione "Assemblea»sguassate u simbulu di compilazione cundizionale R2015 da u campu currispundente
Nota: Ci hè un glitch in l'ultima versione di Visual Studio - i simboli di compilazione cundizionale ùn sò micca visualizati in a finestra di e pruprietà di u prughjettu, ancu s'ellu sò dispunibili. Sè vo avete stu glitch, allura vi tuccherà à sguassà manually da u schedariu .csproj. Tuttavia, avemu sempre à travaglià in questu, cusì leghjite.
Rinominate u prughjettu in a finestra di l'Explorer di Soluzioni sguassate u suffissu _2015 e poi caccià u prugettu da a suluzione. Questu hè necessariu per mantene l'ordine è i sentimenti di perfezionisti! Apertura u cartulare di a nostra suluzione, rinominà u cartulare di u prughjettu in u listessu modu è caricate u prugettu torna in a suluzione.
Aprite u gestore di cunfigurazione. cunfigurazione US Release in principiu, ùn serà micca necessariu, cusì l'eliminemu. Creemu novi cunfigurazioni cù nomi chì sò digià familiarizati per noi R2015, R2016,…, R2020. Nota chì ùn avete micca bisognu di cupià paràmetri da altre cunfigurazioni è ùn avete micca bisognu di creà cunfigurazioni di prughjettu:
Andemu à u cartulare cù u prugettu è apre u schedariu cù l'estensione .csproj in un editore cunvene per voi. Per via, pudete ancu apre in Visual Studio - avete bisognu di scaricà u prugettu è dopu l'elementu ghjustu serà in u menù di cuntestu:
L'edità in Visual Studio hè ancu preferibile, postu chì l'editore sia allinea è invita.
In u schedariu vedemu l'elementi
Andà à l'elementu cumuni (primu). Gruppu di pruprietà è fighjate a pruprietà AssemblyName - questu hè u nome di l'assemblea è ci vole à avè senza suffissu _2015. Se ci hè un suffissu, allora sguassate.
Truvà un elementu cù una cundizione
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
Ùn avemu micca bisognu - l'eliminemu.
Elementu cù una cundizione
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
serà necessariu di travaglià in u stadiu di sviluppu è debug u codice. Pudete cambià e so proprietà per adattà à i vostri bisogni - stabilisce diversi percorsi di output, cambia simboli di compilazione cundizionale, etc.
Avà criemu novi elementi Gruppu di pruprietà per i nostri cunfigurazioni. In questi elementi, avemu solu bisognu di stabilisce quattru proprietà:
- OutputPath - cartulare di output. Aghju stabilitu u valore predeterminatu binR20xx
- Definite Constants sò simboli di compilazione cundiziunali. Si deve esse stabilitu TRACE;R20xx
- TargetFrameworkVersion - versione di piattaforma. Diverse versioni di l'API Revit necessitanu diverse piattaforme per esse stabilite.
- AssemblyName - nome di l'assemblea (vale à dì u nome di u schedariu). Pudete scrive direttamente u nome di l'assemblea desiderata, ma per l'universalità, vi cunsigliu di scrive u valore $(AssemblyName)_20xx. Per fà questu, avemu prima eliminatu u suffissu da u nome di l'assemblea
A funzione più impurtante di tutti questi elementi hè chì ponu esse simpliciamente copiati in altri prughjetti senza cambià in tuttu. Più tardi in l'articulu, aghjustà tuttu u cuntenutu di u schedariu .csproj.
Ebbè, avemu capitu e pruprietà di u prugettu - ùn hè micca difficiule. Ma chì fà cù e librerie incluse (pacchetti NuGet). Se guardemu più, vedemu chì e librerie incluse sò specificate da l'elementi
Un elementu vene à u nostru aiutu
Utilizà l'elementu Scegli, stabilisce diversi pacchetti NuGet per diverse cunfigurazioni:
Tuttu u cuntenutu di csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5AD738D6-4122-4E76-B865-BE7CE0F6B3EB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MySuperPluginForRevit</RootNamespace>
<AssemblyName>MySuperPluginForRevit</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>binDebug</OutputPath>
<DefineConstants>DEBUG;R2015</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2015|AnyCPU' ">
<OutputPath>binR2015</OutputPath>
<DefineConstants>TRACE;R2015</DefineConstants>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AssemblyName>$(AssemblyName)_2015</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2016|AnyCPU' ">
<OutputPath>binR2016</OutputPath>
<DefineConstants>TRACE;R2016</DefineConstants>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AssemblyName>$(AssemblyName)_2016</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2017|AnyCPU' ">
<OutputPath>binR2017</OutputPath>
<DefineConstants>TRACE;R2017</DefineConstants>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<AssemblyName>$(AssemblyName)_2017</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2018|AnyCPU' ">
<OutputPath>binR2018</OutputPath>
<DefineConstants>TRACE;R2018</DefineConstants>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<AssemblyName>$(AssemblyName)_2018</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2019|AnyCPU' ">
<OutputPath>binR2019</OutputPath>
<DefineConstants>TRACE;R2019</DefineConstants>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AssemblyName>$(AssemblyName)_2019</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2020|AnyCPU' ">
<OutputPath>binR2020</OutputPath>
<DefineConstants>TRACE;R2020</DefineConstants>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AssemblyName>$(AssemblyName)_2020</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="PropertiesAssemblyInfo.cs" />
</ItemGroup>
<Choose>
<When Condition=" '$(Configuration)'=='R2015' ">
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2015">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
<When Condition=" '$(Configuration)'=='R2016' ">
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2016">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
<When Condition=" '$(Configuration)'=='R2017' ">
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2017">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
<When Condition=" '$(Configuration)'=='R2018' ">
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2018">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
<When Condition=" '$(Configuration)'=='R2019' ">
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2019">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
<When Condition=" '$(Configuration)'=='R2020' or '$(Configuration)'=='Debug'">
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2020">
<Version>1.0.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(MSBuildToolsPath)Microsoft.CSharp.targets" />
</Project>
Per piacè nutate chì in una di e cundizioni aghju specificatu duie cunfigurazioni via OR. Cusì, u pacchettu necessariu serà cunnessu durante a cunfigurazione Depug.
È quì simu quasi perfetti. Caricà u prughjettu torna, accende a cunfigurazione chì avemu bisognu, chjamate l'articulu "Ripristina tutti i pacchetti NuGet" è vede cumu i nostri pacchetti cambianu.
È in questa tappa, aghju ghjuntu à una strada morta - per cullà tutte e cunfigurazioni in una volta, pudemu usà l'assemblea batch (menu "Assemblea»->«Assemblage batch"), ma quandu cambiate cunfigurazioni, i pacchetti ùn sò micca automaticamente restaurati. È quandu assemble u prughjettu, ùn succede micca ancu, ancu s'ellu, in teoria, deve. Ùn aghju micca trovu una suluzione à stu prublema per mezu standard. È assai prubabilmente questu hè ancu un bug di Visual Studio.
Per quessa, per l'assemblea batch, hè statu decisu di utilizà un sistema d'assemblea automatizatu speciale
Allora, andate à u cartulare di a nostra suluzione (micca u prugettu), mantene a chjave Shift è cliccate dirittu nantu à un spaziu viotu in u cartulare - in u menù di cuntestu, selezziunate l'elementu "Aprite a finestra di PowerShell quì».
Se ùn avete micca installatu nuke, poi prima scrive u cumandamentu
dotnet tool install Nuke.GlobalTool –global
Avà scrive un cumandamentu nuke è vi sarà dumandatu à cunfigurà nuke per u prughjettu attuale. Ùn sò micca sapè cumu scrive in russo currettamente - in inglese serà scrittu Ùn si pudia truvà u schedariu .nuke. Vulete installà una custruzione? [i/n]
Pulsà a chjave Y è dopu ci saranu paràmetri diretti. Vulemu l'opzione più simplice cù l'usu MSBuild, cusì rispondemu cum'è in a screenshot:
Andemu à Visual Studio, chì ci incitarà à ricaricà a suluzione, postu chì un novu prughjettu hè statu aghjuntu. Ricaricate a suluzione è vede chì avemu un prughjettu custruisce in quale simu interessate solu in un schedariu - Custruì.cs
Avemu apertu stu schedariu è scrivite un script per custruisce u prugettu per tutte e cunfigurazioni. Ebbè, o utilizate u mo script, chì pudete edità per voi stessu:
using System.IO;
using Nuke.Common;
using Nuke.Common.Execution;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tools.MSBuild;
using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
[CheckBuildProjectConfigurations]
[UnsetVisualStudioEnvironmentVariables]
class Build : NukeBuild
{
public static int Main () => Execute<Build>(x => x.Compile);
[Solution] readonly Solution Solution;
// If the solution name and the project (plugin) name are different, then indicate the project (plugin) name here
string PluginName => Solution.Name;
Target Compile => _ => _
.Executes(() =>
{
var project = Solution.GetProject(PluginName);
if (project == null)
throw new FileNotFoundException("Not found!");
var build = new List<string>();
foreach (var (_, c) in project.Configurations)
{
var configuration = c.Split("|")[0];
if (configuration == "Debug" || build.Contains(configuration))
continue;
Logger.Normal($"Configuration: {configuration}");
build.Add(configuration);
MSBuild(_ => _
.SetProjectFile(project.Path)
.SetConfiguration(configuration)
.SetTargets("Restore"));
MSBuild(_ => _
.SetProjectFile(project.Path)
.SetConfiguration(configuration)
.SetTargets("Rebuild"));
}
});
}
Riturnemu à a finestra di PowerShell è scrivite u cumandimu novu nuke (pudete scrive u cumandamentu nuke indicà u necessariu destinazione. Ma avemu unu destinazionechì principia per difettu). Dopu appughjà a chjave Enter, ci sentimu cum'è pirate veri, perchè, cum'è in un filmu, u nostru prughjettu serà automaticamente assemblatu per diverse cunfigurazioni.
A propositu, pudete aduprà PowerShell direttamente da Visual Studio (menu "vista,»->«Altre finestre»->«Console di gestione di pacchetti"), ma tuttu serà biancu è biancu, chì ùn hè micca assai cunvenutu.
Questu cuncludi u mo articulu. Sò sicuru chì pudete scopre l'opzione per AutoCAD stessu. Spergu chì u materiale prisentatu quì truverà i so "clienti".
Ti ringraziu per a vostra attenzione!
Source: www.habr.com