Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

CAD alkalmazások bővítmények fejlesztésekor (az én esetemben ez az AutoCAD, Revit és Renga) idővel felmerül egy probléma – új verziók jelennek meg a szoftverekből, változik az API-juk, és új bővítményverziókat kell készíteni.

Ha csak egy bővítménye van, vagy még új a szakmában, akkor egyszerűen elkészítheti a projekt egy másolatát, módosíthatja a szükséges részeket, és összeállíthatja az új bővítményverziót. Ennek megfelelően a kód módosítása jelentős többletköltségekkel jár.

A tapasztalat és tudás felhalmozódásával több módszert is talál a folyamat automatizálására. Ezt az utat jártam be, és szeretném megosztani Önnel, hogy hová jutottam, és mennyire kényelmes ez.

Először nézzük meg a nyilvánvaló módszert, amelyet sokáig használtam.

Hivatkozások a projekt fájlokra

És hogy mindez egyszerű, világos és érthető legyen, egy absztrakt bővítményfejlesztési példán keresztül fogom leírni.

Nyissuk meg a Visual Studio-t (nekem a Community 2019-es verzió van, és igen - orosz nyelven), és hozzunk létre egy új megoldást. Nevezzük el MySuperPluginForRevit

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Bővítményt készítünk a Revit számára a 2015-2020-as verziókhoz. Ezért létrehozok egy új projektet a megoldásban (Class Library .NET Framework) és nevezzük el MySuperPluginForRevit_2015

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Hivatkozásokat kell adni az API Revit-re. Természetesen hozzáadhatjuk a hivatkozásokat helyi fájlokhoz (telepíteni kell az összes szükséges SDK-t vagy a Revit összes verzióját), de mi azonnal a helyes úton haladunk, és csatlakoztatjuk a NuGet csomagot. Számos csomagot találhat, de én a sajátomat fogom használni.

A csomag csatlakoztatása után kattintsunk jobb gombbal a "Hivatkozások" elemre, majd a menüben válasszuk az "A packages.config áthelyezése PackageReference-be...»

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Ha ezen a ponton pánikba esne, mivel a csomag tulajdonságainak ablakában nem találja a fontos "Helyi másolás" elemet, amelyet feltétlenül " hamisra kell állítani, ne pánikoljon - lépjünk be a projekthez tartozó mappába, nyissuk meg a .csproj kiterjesztésű fájlt egy tetszőleges szerkesztőben (én a Notepad++-t használom), és ott keressük meg a csomagunkra vonatkozó bejegyzést. Jelenleg így néz ki:

1.0.0

Adjunk hozzá neki egy tulajdonságot, runtime. Így fog kinézni:

1.0.0
  runtime

Most már a projekt létrehozásakor a csomag fájljai nem kerülnek átmásolásra a kimeneti mappába.
Tovább haladva – képzeljük el, hogy a pluginunk használni fog valamit a Revit API-ból, ami az új verziók megjelenésével változott. Vagy egyszerűen szükségünk van arra, hogy valamit megváltoztassunk a kódban a Revit verziótól függően, amelyhez a plugint készítjük. Az ilyen kódeltérések kezelésére feltételes fordítási szimbólumokat fogunk használni. Nyissuk meg a projekt tulajdonságait, lépjünk a "Összeállítás" fülre és a "Feltételes fordítási jelzések" mezőbe írjuk be R2015.

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Vegyük figyelembe, hogy a szimbólumot a Debug és a Release konfigurációhoz is hozzá kell adni.

Amíg a tulajdonságok ablakában vagyunk, azonnal lépjünk a "Az alkalmazás" fülre és a "Alapértelmezett névtér" fülre, és távolítsuk el a végződést _2015, hogy a névtér univerzális és független legyen a gyűjtemény nevétől:

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Az én esetemben az összes verzió pluginjai ugyanabba a mappába kerülnek, ezért a gyűjtemények nevei a _20xxvégződésűek maradnak. De eltávolíthatja a végződést a gyűjtemény nevéből is, ha a fájlok különböző mappákban lesznek.

Lépjünk a Class1.cs fájl kódjára, és ott szimuláljunk egy kódot a különböző Revit verziók figyelembevételével:

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", "Helló Revit 2015");
#elif R2016
            TaskDialog.Show("ModPlus", "Helló Revit 2016");
#elif R2017
            TaskDialog.Show("ModPlus", "Helló Revit 2017");
#elif R2018
            TaskDialog.Show("ModPlus", "Helló Revit 2018");
#elif R2019
            TaskDialog.Show("ModPlus", "Helló Revit 2019");
#elif R2020
            TaskDialog.Show("ModPlus", "Helló Revit 2020");
#endif
            return Result.Succeeded;
        }
    }
}

Az összes Revit verziót figyelembe vettem, amelyek a 2015-ös verzió felett vannak (amikor a cikket írták), és figyelembe vettem a feltételes fordítási szimbólumok meglétét, amelyeket azonos sablon alapján hozok létre.

Most lépjünk a fő különlegességhez. Hozzunk létre egy új projektet a megoldásunkban, már a Revit 2016 verzióhoz készült plugin számára. Ismételjük meg az összes fent említett lépést, megfelelően helyettesítve a 2015-öt 2016-ra. De a fájlt Class1.cs az új projektből eltávolítjuk.

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

A szükséges kód fájl - Class1.cs - már rendelkezésünkre áll, és csak hivatkoznunk kell rá az új projektben. Két hivatkozási mód létezik:

  1. Hosszú – kattintson a projektben a jobb gombbal, válassza a „Hozzáadás” -> „Létező elem”, az előugró ablakban keresse meg a szükséges fájlt, és a „Hozzáadás” opció helyett válassza a „Hozzáadás kapcsolataként»

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

  1. Rövid – közvetlenül a megoldásböngészőben válassza ki a szükséges fájlt (vagy akár fájlokat. Sőt, akár egész mappákat is), és húzza át az új projektbe, miközben lenyomva tartja az Alt billentyűt. Amikor húzza, látni fogja, hogy amikor lenyomva tartja az Alt billentyűt, az egérkurzor a pluszból nyílra változik.
    UPD: Egy kicsit zavarosá tettem ezt a bekezdést – hogy több fájlt mozgathasson, nyomja le a Shift+Alt!

A folyamat elvégzése után a második projektben megjelenik a fájl Class1.cs a megfelelő ikonképpel (kék nyíl):

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

A kód szerkesztésekor a szerkesztőablakban azt is kiválaszthatja, hogy melyik projekt kontextusában jelenjen meg a kód, ami lehetővé teszi, hogy a kódot különböző feltételes fordítási szimbólumok szerint lássa és szerkessze:

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Ezen séma szerint hozzuk létre a többi projektet (2017-2020). Praktikus tipp – ha a megoldásböngészőben nem az alap projektről, hanem arról a projektről húzza át a fájlokat, ahol már kapcsolatként vannak beillesztve, akkor nem szükséges lenyomva tartani az Alt billentyűt!

A leírt megoldás egészen addig jó, amíg nem adunk hozzá új verziót a pluginnak, vagy új fájlokat a projekthez – minden nagyon bonyolulttá válik. És nemrégiben hirtelen rájöttem, hogyan tudom mindezt egy projekttel megoldani, és most átmegyünk a második módszerre.

A konfigurációk varázsa

Miután idáig eljutott, kiálthatja: „Miért írtad le az első módszert, ha a cikk azonnal a másodikra készült?!”. Azért írtam le mindezt, hogy világosabb legyen, mire van szükségünk a feltételes fordítási szimbólumokhoz, és hol különböznek a projektjeink. Így most világossá válik, hogy pontosan mely különbségeket kell megvalósítanunk, csak egy projektet hagyva.

És hogy minden egyértelműbb legyen, nem hozunk létre új projektet, hanem módosításokat végzünk a jelenlegi projektünkön, amit az első mód szerint hoztunk létre.

Először is távolítsa el a megoldásból az összes projektet, kivéve az alapvetőt (amely tartalmazza a közvetlen fájlokat). Azaz a 2016-2020 közötti projekteket. Nyissa meg a megoldás mappáját, és törölje az ezeknek a projekteknek a mappáit.

A megoldásunkban csupán egy projekt maradt – MySuperPluginForRevit_2015. Nyissa meg a tulajdonságait, és:

  1. A „Az alkalmazás” fülön a build névéből távolítsa el a végződést, _2015 (később világos lesz, miért)
  2. A „Összeállítás» eltávolítjuk a feltételes fordítási szimbólumot R2015 a megfelelő mezőből

Megjegyzés: a Visual Studio legutolsó verziójában van egy hiba – a feltételes fordítási szimbólumok nem jelennek meg a projekt tulajdonságai ablakában, bár ott vannak. Ha Ön is tapasztalja ezt a hibát, akkor manuálisan kell eltávolítania őket a .csproj fájlból. Azonban továbbra is dolgozunk benne, úgyhogy folytassuk.

Átnevezzük a projektet a megoldás fájlkezelőjében, eltávolítva a végződést _2015 és ezután eltávolítjuk a projektet a megoldásból. Erre azért van szükség, hogy rendet tartsunk és kielégítsük a maximalisták igényeit! Megnyitjuk a megoldás mappáját, ugyanígy átnevezzük a projekt mappáját és visszatöltjük a projektet a megoldásba.

Megnyitjuk a konfigurációkezelőt. A konfiguráció Kiadás elvileg nem lesz szükségünk, ezért eltávolítjuk. Új konfigurációkat hozunk létre a már megszokott nevekkel R2015, R2016, …, R2020. Vegye figyelembe, hogy nem szükséges más konfigurációkból másolni a beállításokat, és nem szükséges projektkonfigurációt létrehozni:

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Elmegyünk a projekthez tartozó mappába, és megnyitjuk a .csproj kiterjesztésű fájlt az Ön által preferált szerkesztőben. Egyébként meg lehet nyitni a Visual Studio-ban is – ki kell üríteni a projektet, majd a helyi menüben megtalálható a szükséges opció:

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

A Visual Studio-ban való szerkesztés még előnyösebb, mivel a szerkesztő igazít és javaslatokat ad.

A fájlban látni fogjuk az elemeket PropertyGroup – a legfelső elem általános, utána következnek a feltételekkel. Ezek az elemek beállítják a projekt tulajdonságait a fordítás során. Az első elem, amely nem tartalmaz feltételt, az általános tulajdonságokat állítja be, míg a feltételekkel rendelkező elemek ennek megfelelően megváltoztatják a tulajdonságokat a konfigurációk függvényében.

Átmegyünk az általános (első) elemhez PropertyGroup és megnézzük a tulajdonságot AssemblyName – ez a gyűjtemény neve, és ez nálunk végződés nélkül kell, hogy legyen _2015. Ha van végződés, akkor eltávolítjuk azt.

Megkeressük a feltétellel rendelkező elemet

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

Ez nekünk nem szükséges – eltávolítjuk.

A feltétellel rendelkező elem

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

szükséges lesz a kód fejlesztési és hibakeresési szakaszában. Megváltoztathatja a tulajdonságait az Ön igényei szerint – különböző kimeneti utakat állíthat be, módosíthatja a feltételes fordítási szimbólumokat stb.

Most új elemeket hozunk létre PropertyGroup a konfigurációnkhoz. Ezeknél az elemeknél elegendő négy tulajdonságot megadni:

  • OutputPath – kimeneti mappa. Én az alapértelmezett értéket állítom be binR20xx
  • DefineConstants – a feltételes fordítási karakterek. Értéket kell megadni TRACE;R20xx
  • TargetFrameworkVersion – a platform verziója. Különböző Revit API verziókhoz más platformokat kell megadni.
  • AssemblyName – a szerelvény neve (tehát a fájl neve). Megadhatja a szükséges szerelvény nevét, de az univerzalitás érdekében javaslom, hogy a következő értéket írja be $(AssemblyName)_20xx. Ezt korábban a szerelvény nevéből távolítottuk el.

A legfontosabb dolog ezekben az elemekben az, hogy más projektekbe anélkül is egyszerűen másolhatók, hogy bármit is módosítanánk. A cikk további részében csatolni fogom a .csproj fájl teljes tartalmát.

Nos, a projekt tulajdonságaival már tisztában vagyunk – ez nem nehéz. De mi a helyzet a használt könyvtárakkal (NuGet-csomagok). Ha tovább nézzük, láthatjuk, hogy a használt könyvtárakat az alábbi elemekben adjuk meg ItemGroup. De itt a probléma – ez az elem hibásan kezeli a feltételeket, mint az elem PropertyGroup. Lehetséges, hogy ez akár a Visual Studio hibája is, de ha több elemet adunk meg ItemGroup feltételekkel, és belül különböző hivatkozásokat illesztünk be a NuGet-csomagokra, akkor a konfigurációk váltásakor a projekthez minden megadott csomag kapcsolódik.

Segítségünkre jön az elem Válaszd, amely a megszokott logika alapján működik if-then-else.

Az elem használatával Válaszd, különböző NuGet-csomagokat adunk meg különböző konfigurációkhoz:

A csproj teljes tartalma

Debug
    AnyCPU
    {5AD738D6-4122-4E76-B865-BE7CE0F6B3EB}
    Library
    Properties
    MySuperPluginForRevit
    MySuperPluginForRevit
    v4.5
    512
    true
  
  
    true
    full
    false
    binDebug
    DEBUG;R2015
    prompt
    4
  
  
    binR2015
    TRACE;R2015
    v4.5
    $(AssemblyName)_2015
  
  
    binR2016
    TRACE;R2016
    v4.5
    $(AssemblyName)_2016
  
  
    binR2017
    TRACE;R2017
    v4.5.2
    $(AssemblyName)_2017
  
  
    binR2018
    TRACE;R2018
    v4.5.2
    $(AssemblyName)_2018
  
  
    binR2019
    TRACE;R2019
    v4.7
    $(AssemblyName)_2019
  
  
    binR2020
    TRACE;R2020
    v4.7
    $(AssemblyName)_2020
  
  
    
    
    
    
    
    
    
    
  
  
    
    
  
  
    
      
        
          1.0.0
          runtime
        
      
    
    
      
        
          1.0.0
          runtime
        
      
    
    
      
        
          1.0.0
          runtime
        
      
    
    
      
        
          1.0.0
          runtime
        
      
    
    
      
        
          1.0.0
          runtime
        
      
    
    
      
        
          1.0.0
          runtime

Kérjük, vegye figyelembe, hogy az egyik feltételben két konfigurációt adtam meg a VAGY (Or). Így a megfelelő csomag kapcsolódik a konfiguráció során. Hibaelhárítás.

És most már majdnem minden tökéletes. Visszatöltjük a projektet, aktiváljuk a szükséges konfigurációt, majd a megoldás (nem a projekt) helyi menüjében kiválasztjuk a „Minden NuGet-csomag helyreállítása” lehetőséget, és látjuk, ahogy a csomagjaink változnak.

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

És ezen a ponton elakadtam – ha egyszerre szeretnénk összeállítani az összes konfigurációt, élhetnénk a csomagolt build lehetőséggel (a „Összeállítás” -> „Csomagolt build” menü), de a konfigurációk váltásakor nem történik automatikus helyreállítás a csomagok számára. A projekt összeállítása során sem történik meg, pedig elméletileg meg kellene. Erre a problémára nem találtam megoldást a standard eszközökkel. Valószínűleg ez is egy hiba a Visual Studio-ban.

Ezért a csomagolt buildhez egy speciális automatizált build rendszert választottunk, Nuke. Valójában ezt nem akartam, mivel túlzásnak tartom a plugin fejlesztése során, de jelenleg nem látok más megoldást. A kérdésre, hogy „Miért éppen Nuke?” a válasz egyszerű – a munkahelyen ezt használjuk.

Tehát lépjünk be a megoldásunk mappájába (nem a projekt mappájába), nyomjuk meg az Shift billentyűt, és kattintsunk jobb gombbal egy üres helyre a mappában – a helyi menüben válasszuk a „PowerShell ablak megnyitása itt».

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Ha nincs telepítve a nuke, akkor először írja be a parancsot

dotnet tool install Nuke.GlobalTool –global

Most írja be a parancsot nuke és felajánlja, hogy konfigurálja a nuke aktuális projekthez. Nem tudom, hogyan kell ezt a lehető legjobban megfogalmazni magyarul – angolul az lesz írva: Could not find .nuke file. Do you want to setup a build? [y/n]

Megnyomjuk az Y billentyűt, és további beállítási lehetőségek következnek. A legjobb, ha a legegyszerűbb verziót használjuk, amely MSBuild, ezért úgy válaszolunk, ahogy a képernyőképen van:

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Átmegyünk a Visual Studio-ba, amely azt javasolja, hogy töltsük újra a megoldást, mivel új projektet adtak hozzá. Újra töltsük be a megoldást, és látjuk, hogy megjelent a projekt, build amelyben csak egy fájl érdekel minket – Build.cs

Egy plugin projektet készítünk, amely különböző Revit / AutoCAD verziókra van összeállítva.

Megnyitjuk ezt a fájlt, és írunk egy build szkriptet az összes konfigurációhoz. Vagy használhatja az én szkriptemet, amelyet átírhat saját magának:

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(x => x.Compile);

    [Solution] readonly Solution Solution;

    // Ha a megoldás neve és a projekt (plugin) neve eltérő, itt jelezze a projekt (plugin) nevét
    string PluginName => Solution.Name;

    Target Compile => _ => _
        .Executes(() =>
        {
            var project = Solution.GetProject(PluginName);
            if (project == null)
                throw new FileNotFoundException("Nem található!");

            var build = new List();
            foreach (var (_, c) in project.Configurations)
            {
                var configuration = c.Split("|")[0];

                if (configuration == "Debug" || build.Contains(configuration))
                    continue;

                Logger.Normal($"Konfiguráció: {configuration}");

                build.Add(configuration);

                MSBuild(_ => _
                    .SetProjectFile(project.Path)
                    .SetConfiguration(configuration)
                    .SetTargets("Restore"));
                MSBuild(_ => _
                    .SetProjectFile(project.Path)
                    .SetConfiguration(configuration)
                    .SetTargets("Rebuild"));
            }
        });
}

Térjünk vissza a PowerShell ablakhoz és írjuk be újra a parancsot nuke (be lehet írni a parancsot nuke a szükséges megadásával Target. De nekünk itt egy Target, ami alapértelmezetten elindul). Az Enter billentyű megnyomása után úgy érezzük magunkat, mint egy igazi hacker, mivel a filmben automatikusan történik a projektünk különböző konfigurációk szerinti összeállítása.

Sőt, a PowerShell-t közvetlenül a Visual Studio-ból is használhatjuk (a "Nézet” -> „Egyéb ablakok” -> „Csomagkezelő konzol"), de ott minden fekete-fehér lesz, ami nem túl kényelmes.

Ezzel befejeztem a cikkemet. Biztos vagyok benne, hogy az AutoCAD variációval egyedül is boldogul majd. Remélem, hogy az itt bemutatott anyag megtalálja a "klienseit".

Köszönöm a figyelmet!

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster