Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

CAD rakenduste pistikute arendamisel (minu puhul on see AutoCAD, Revit ja Renga) tekib aja jooksul üks probleem – ilmuvad uued programmid, muutub nende API ja tuleb teha uusi pistikute versioone.

Kui teil on vaid üks pistik või olete selles osas veel algaja-isetegija, siis saate lihtsalt projekti koopia teha, muuta vajalikud kohad ja koostada pistiku uus versioon. Vastavalt sellele toob edasine koodimuudatus endaga kaasa tööjõu märgatava suurenemise.

Kogemuste ja teadmiste kogunemise käigus leiate mitu viisi selle protsessi automatiseerimiseks. Olen läbinud selle tee ja tahan teile rääkida, kuhu ma lõpuks jõudsin ja kui mugav see on.

Alustame viisist, mis on ilmselge ja millega ma pikka aega kasutasin

Lingid projekti failidele

Ja et kõik oleks lihtne, arusaadav ja selge, kirjeldan kõike abstraktses näites pistiku arendamisest.

Avame Visual Studio (mul on versioon Community 2019. Ja jah – vene keeles) ja loome uue lahenduse. Nimeks anname MySuperPluginForRevit

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Me loome Revitile plugina versioonide 2015-2020 jaoks. Seetõttu loon lahendusse uue projekti (Net Frameworki klasside raamatukogu) ja nimetame selle MySuperPluginForRevit_2015

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Peame lisama viiteid Revit API-le. Muidugi võime lisada viiteid lokaalsetele failidele (kuna peab endale installima kõik vajalikud SDK-d või kõik Revit versioonid), kuid me läheme kohe õiget teed ja ühendame NuGet-paketi. Võite leida mitmeid pakette, kuid mina kasutan oma omi.

Pärast paketi ühendamist klõpsake paremklõpsuga punktile «Lingid» ja valige menüüs punkt «Kanda packages.config üle PackageReference…»

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Kui äkki hakkab selles kohas teil paanikahoog, kuna paketi omaduste aknas ei ole olulist punkti «Kopeeri lokaalselt», mille me peame kindlasti seadistama väärtuseks false, siis ei tasu paanikasse minna – läheme projekti kausta, avame .csproj laiendiga faili mugavas redigeerijas (mina kasutan Notepad++) ja otsime sealt üles kirje oma paketi kohta. See näeb praegu välja nii:

1.0.0

Lisame sellele omaduse runtime. Tuleb välja nii:

1.0.0
  runtime

Nüüd, kui projekt on loodud, ei kopeerita paketi faile väljundkausta.
Jätkame – eeldame kohe, et meie plugin kasutab midagi Revit API-st, mis on aja jooksul uute versioonide väljalaskmisega muutunud. Või lihtsalt peame koodis midagi oma versiooni Revit-i järgi muutma, millele me plugina teeme. Selliste koodierinevuste lahendamiseks kasutame tingimuslikke kompileerimissümboleid. Avame projekti omadused, läheme vahekaardile „Koostamine“ ja kirjutame väljadele „Tingimusliku kompileerimise sümbolidR2015.

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Pange tähele, et sümbol tuleb lisada nii Debug- kui ka Release-konfiguratsioonide jaoks.

Ja kuni oleme omaduste aknas, liigume kohe vahekaardile „Rakendus“ ja kirjutame väljadele „Vaikimisi nimespatsioon“ ja eemaldame suffiksi _2015, et meie nimespatsioon oleks universaalne ja sõltumatu kogumi nimest:

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Minu puhul kogunevad lõppproduktis pluginaid kõigis versioonides ühte kausta, seega jäävad minu koguse nimed suffiksiga nagu _20xx. Kuid saate lisandmooduli nimest sufiksi eemaldada, kui failide asukoht on erinevatesse kaustadesse jagatud.

Liigume faili koodi juurde Class1.cs ja simuleerime seal mingit koodi, arvestades erinevaid Revit versioone:

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

Arvestasin kohe kõiki Revit versioone, mis olid kõrgemad kui 2015 (mis olid artikli kirjutamise ajal olemas) ja arvestasin kohe ka tingimuslike kompileerimise sümbolite olemasolu, mis mul luuakse sama malli alusel.

Liigume pearikka saanud osani. Loome meie lahenduses uue projekti, kuid seekord Revit 2016 plugina versioonile. Korrame eelnevaid samme, asendades numbrit 2015 numbriga 2016. Kuid faili Class1.cs uusest projektist kustutame.

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Fail, mille on vajalik kood – Class1.cs – on meil juba olemas ja peame lihtsalt sellele uues projektis linki lisama. Linkide lisamiseks on kaks võimalust:

  1. Pikk – klikime projektile hiire parema nupuga, valime punkti „Lisa” -> „Olemasolev element”, avaneb aknas vajaliku faili leidmiseks ja valime „Lisa” asemel valiku „Lisa lingina»

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

  1. Lühike – otse lahenduste avajas valime vajaliku faili (või isegi failid. Võib isegi terveid kaustu) ja lohistame uuele projekti, hoides all klahvi Alt. Loendamisel näete, et Alt-klahvi all hoides muutub hiire kursor plussilt nooleks.
    UPD: Ma tegin selles lõigus veidi segadust – mitu faili üle kandmiseks tuleks hoida all Shift+Alt!

Pärast protseduuri läbiviimist on meil teises projektis fail Class1.cs vastava ikooniga (sinine nool):

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Koodi redigeerimise ajal redigeerimisaknas saate samuti valida, millises projekti kontekstis koodi kuvada, mis võimaldab teil näha koodi redigeerida erinevate tingimuslike kompileerimise sümbolite korral:

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Selle skeemi abil loome kõik teised projektid (2017-2020). Elu pettus – kui lohistate faile lahenduste vaatjas mitte põhprojekti, vaid projektist, kus need on juba sidemena lisatud, ei pea Alt-klahvi all hoidma!

Kirjeldatud variant on täiesti hea, kuni lisatakse uus plugina versioon või lisatakse projekti uusi faile – see kõik muutub väga vaevaseks. Ja hiljuti taipasin, kuidas seda kõike ühe projektiga kenasti lahendada, ning liigume teise meetodi juurde.

Konfiguratsiooni maagia

Siia lugedes võite hüüda: "Miks sa esimest meetodit kirjeldasid, kui artikkel räägib kohe teisest?!" Ja kirjutasin kõik selleks, et oleks selgem, miks meil on vaja tingimusliku kompileerimise sümboleid ja millistes kohtades meie projektid erinevad. Nüüd on selgem, millised täpsed erinevused projektides tuleb ellu viia, jättes vaid ühe projekti.

Ja et kõik oleks selgem, ei loo me uut projekti, vaid teeme muudatused meie praeguses projektis, mis loodi esimese meetodi abil.

Esiteks eemaldame lahendusest kõik projektid peale peamise (millel on otseselt failid). St projektid aastatest 2016–2020. Avame lahenduse kausta ja eemaldame seal nende projektide kaustad.

Meie lahenduses on jäänud alles üks projekt — MySuperPluginForRevit_2015. Avame tema omadused ja:

  1. Vahekaardil "Rakendus" eemaldame kogumi nimest suffiksi _2015 (edasi saab selgeks, miks)
  2. Vahekaardil "Koostamine" eemaldame tingimusliku kompileerimise sümboli R2015 vastavast väljast

Märkus: viimasel versioonil Visual Studio's on tõrge — tingimusliku kompileerimise sümbolid ei kuvata projekti omaduste aknas, kuigi need on olemas. Kui see tõrge Teil esineb, peaksite need käsitsi .csproj failist eemaldama. Kuid me peame sellega edasi tegutsema, seega loeme edasi.

Nimeta projekt lahenduse aknas ümber, eemaldades suffiksi _2015 ja seejärel eemaldame projekti lahendusest. See on vajalik korrashoiu ja perfektsionistide tunnete säilitamiseks! Avame meie lahenduse kausta, nimeta projektikaust seal sama moodi ümber ja laadime projekti tagasi lahendusse.

Avame konfiguratsioonihalduri. Meile on vajalik konfiguratsioon Release põhimõtteliselt ei ole vajalik, seega kustutame selle. Loome uued konfiguratsioonid juba tuttavate nimedega. R2015, R2016, …, R2020. Pange tähele, et ei ole vaja kopeerida parameetreid teistest konfiguratsioonidest ega luua projekti konfiguratsioone:

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Liigume projekti kausta ja avame .csproj laiendiga faili meelepärases redigeerijas. Muide, seda saab avada ka Visual Studio's – tuleb projekt lahti laadida ja kontekstimenüüs on vajalik punkt:

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Redigeerimine Visual Studios on isegi eelistatavam, kuna redaktor joondab ja annab vihjeid.

Failis näeme elemente PropertyGroup – ülemine element on üldine ja seejärel tingimustega. Need elemendid määravad projekti omadused selle kompileerimisel. Esimene element, mis on tingimusteta, määrab üldised omadused, samas kui tingimustega elemendid muudavad vastavalt mõningaid omadusi sõltuvalt konfiguratsioonidest.

Liigume üldise (esimese) elemendi juurde PropertyGroup ja vaatame omadust AssemblyName – see on kogumi nimi ja see peaks olema meil ilma sufiksita _2015. Kui sufiks on olemas, siis kustutame selle.

Otsime tingimusega elementi

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

See ei ole meile vajalik – kustutame selle.

Element tingimusega

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

on vajalik koodi arendamise ja silumise faasis. Saate muuta selle omadusi vastavalt oma vajadustele – seadistada erinevaid väljundite teid, muuta tingimusliku kompileerimise sümboleid jne.

Nüüd loome uusi elemente PropertyGroup meie konfiguratsioonide jaoks. Nendes elementides peame kõige olulisemad neli omadust seadistama:

  • OutputPath – väljundkaust. Määran standardväärtuse binR20xx
  • DefineConstants – tingimusliku kompileerimise sümbolid. Tuleb määrata väärtus TRACE;R20хх
  • TargetFrameworkVersion – platvormi versioon. Erinevate Revit API versioonide jaoks tuleb määrata erinevad platvormid.
  • AssemblyName – kogumi nimi (st faili nimi). Saate kirjutada otse vajaliku kogumi nime, kuid universaalsuse huvides soovitan kirjutada väärtus $(AssemblyName)_20хх. Selleks eemaldasime varem kogumi nimest sufiksi

Kõige tähtsam funktsioon nende elementide puhul on see, et neid saab lihtsalt kopeerida teistesse projektidesse, ilma et neid tuleks muuta. Järgmises artiklis lisatakse kõik .csproj faili sisu.

Nii, projekti omadused on selged – see ei ole keeruline. Aga kuidas on asjadega, mis puudutavad lisakogusid (NuGet paketid)? Edasi liikudes näeme, et lisakogused määratakse elementides. ItemGroup. Kuid siin on probleem – see element töötleb tingimusi valesti nagu element. PropertyGroup. See võib olla isegi Visual Studio viga, kuid kui määrata mitu elementi ItemGroup konfiguratsiooni tingimustega ja lisada sisse erinevad viidatud NuGet paketid, siis konfiguratsiooni muutmisel ühendatakse projekti kõik määratud paketid.

Meie appi tuleb element Valige, mis töötab tuttava loogika alusel. if-then-else.

Kasutan elementi Valige, et määrata erinevad NuGet paketid erinevate konfiguratsioonide jaoks:

Kogu sisu csproj

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

Pange tähele, et ühes tingimusest olen ma määranud kaks konfiguratsiooni läbi VÕI (Or). Seega ühendatakse vajalik pakett konfiguratsiooni puhul Debug.

Ja nüüd on meil peaaegu kõik ideaalne. Laeme projekti tagasi, aktiveerime vajaliku konfiguratsiooni, valime kontekstimenüüst (mitte projekti) punkti „Taasta kõik NuGet paketid” ja näeme, kuidas meie paketid muutuvad.

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Ja nüüd olen ma selle etapi juures ummikseisus – et koguda kõik konfiguratsioonid, võiksime kasutada paketihaldust (menüü „Koostamine” -> „Paketihaldus”), kuid konfiguratsioonide vahetamisel ei toimu automaatset taastamist. Samuti ei toimu projektide kogumisel, kuigi peaks. Standardsete vahendite abil ei ole ma selle probleemi lahendust leidnud. Ja tõenäoliselt on see ka Visual Studio tõrge.

Seetõttu oli paketihalduses otsustatud kasutada spetsiaalset automatiseeritud kogumissüsteemi Nuke. Tegelikult ei tahtnud ma seda, kuna pean seda pluginade arendamise raames liialdama, kuid hetkel ei näe ma muud lahendust. Ja küsimusele "Miks just Nuke?" on vastus lihtne – kasutame tööl.

Nüüd liigume lahenduse kausta (mitte projekti), hoidke klahvi Shift ja klõpsake kaustas tühjal kohal hiire parema nupuga – kontekstimenüüst valige "Ava PowerShell aken siin».

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Kui teil ei ole installitud nuke, siis kirjutage esmalt käsk

dotnet tool install Nuke.GlobalTool –global

Nüüd kirjutage käsk nuke ja teilt palutakse seadistada nuke praeguse projekti jaoks. Ma ei tea, kuidas see õigemini vene keeles kirjutada – inglise keeles kirjutatakse Could not find .nuke file. Do you want to setup a build? [y/n]

Vajutame klahvi Y ja edasi tulevad otsesed seadistamise punktid. Meile on vajalik kõige lihtsam variant koos MSBuild, seega vastame nagu ekraanipildil:

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Liigume Visual Studio'sse, mis pakub meile lahenduse taaskäivitamist, kuna sellesse on lisatud uus projekt. Taaskäivitame lahenduse ja näeme, et meil on nüüd projekt build milles meid huvitab ainult üks fail – Build.cs

Loome ühe projekti pistikprogrammi jaoks, mis on koostatav erinevate versioonide Revit / AutoCAD jaoks.

Avame selle faili ja kirjutame projekti koostamise skripti kõikide konfiguratsioonide alla. Või kasutame minu skripti, mida saate enda jaoks redigeerida:

kasutades System.IO;
kasutades Nuke.Common;
kasutades Nuke.Common.Execution;
kasutades Nuke.Common.ProjectModel;
kasutades Nuke.Common.Tools.MSBuild;
kasutades staatiline Nuke.Common.Tools.MSBuild.MSBuildTasks;

[CheckBuildProjectConfigurations]
[UnsetVisualStudioEnvironmentVariables]
klass Build : NukeBuild
{
    avalik staatiline int Main () => Execute<Build>(x => x.Compile);

    [Solution] readonly Solution Solution;

    // Kui lahenduse ja projekti (plugin) nimed on erinevad, siis näidake projekti (plugin) nime siin
    string PluginName => Solution.Name;

    Target Compile => _ => _
        .Executes(() =>
        {
            var project = Solution.GetProject(PluginName);
            if (project == null)
                throw new FileNotFoundException("Ei leitud!");

            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($"Konfiguratsioon: {configuration}");

                build.Add(configuration);

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

Naaseme PowerShelli aknasse ja kirjutame jälle käsu nuke (võime kirjutada käsu nuke vajalikega Target. Aga meil on üks Target, mis käivitub vaikimisi). Pärast Enter-klahvi vajutamist tunneme end tõeliste häkkeritena, sest nagu filmis toimub automaatne meie projekti koostamine erinevate konfiguratsioonide jaoks.

Muide, PowerShelli saab kasutada otse Visual Studios (menüüs «Vaade” -> „Teised aknad” -> „Pakettide halduri konsool»), kuid seal on kõik must-valge, mis ei ole väga mugav.

Minu artikkel on siin nun valmis. Olen kindel, et AutoCADi versiooniga saate ise hakkama. Loodan, et siin esitatud materjal leiab oma «kliendid».

Aitäh tähelepanu eest!

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster