
عند تطوير المكونات الإضافية لتطبيقات CAD ( في حالتي ، أوتوكاد و Revit و Renga) ، تنشأ مشكلة بمرور الوقت - ظهور إصدارات جديدة من البرامج وتغييرات واجهة برمجة تطبيقاتها وإصدارات جديدة من المكونات الإضافية.
عندما يكون لديك مكون إضافي واحد فقط أو كنت لا تزال مبتدئًا في هذا الأمر ، يمكنك ببساطة إنشاء نسخة من المشروع وتغيير الأماكن اللازمة فيه وإنشاء نسخة جديدة من المكون الإضافي. وفقًا لذلك ، ستستتبع التغييرات اللاحقة على الكود زيادة متعددة في تكاليف العمالة.
مع اكتساب الخبرة والمعرفة ، ستجد عدة طرق لأتمتة هذه العملية. ذهبت بهذه الطريقة وأريد أن أخبركم بما جئت إليه في النهاية ومدى ملائمته.
للبدء ، فكر في طريقة واضحة وأستخدمها لفترة طويلة
روابط لملفات المشروع
ولجعل كل شيء بسيطًا وواضحًا ومفهومًا ، سوف أصف كل شيء باستخدام مثال تجريبي لتطوير المكونات الإضافية.
افتح Visual Studio (لدي إصدار Community 2019. ونعم - باللغة الروسية) وقم بإنشاء حل جديد. دعنا نسميها MySuperPluginForRevit

سنقوم بعمل ملحق لبرنامج Revit للإصدارات 2015-2020. لذلك ، سنقوم بإنشاء مشروع جديد في الحل (مكتبة Net Framework Class) وسنسميها MySuperPluginForRevit_2015

نحن بحاجة إلى إضافة روابط إلى Revit API. بالطبع ، يمكننا إضافة روابط إلى الملفات المحلية (ستحتاج إلى تثبيت جميع SDKs اللازمة أو جميع إصدارات Revit) ، لكننا سنمضي على الطريق الصحيح مباشرة ونربط حزمة NuGet. لا يمكنك العثور على عدد صغير من الحزم ، لكنني سأستخدم حزمتي الخاصة.
بعد توصيل الحزمة ، انقر بزر الماوس الأيمن على عنصر " الروابط " وحدد " نقل الحزم. قم بتكوين الحزم إلى PackageReference ... " في القائمة

إذا أصبت بالذعر فجأة في هذه المرحلة ، نظرًا لأن نافذة خصائص الحزمة لا تحتوي على العنصر المهم " نسخ محليًا " ، والذي نحتاج بالتأكيد إلى تعيينه على " خطأ" ، فلا داعي للذعر - انتقل إلى مجلد المشروع وافتح الملف بالملحق. csproj في محرر مناسب (يمكنني استخدام Notepad ++) ونجد أن هناك سجلًا حول الحزمة الخاصة بنا. يبدو هذا الآن:
<PackageReference Include="ModPlus.Revit.API.2015"> <Version>1.0.0</Version> </PackageReference>
أضف خاصية <ExcludeAssets> وقت التشغيل </ ExcludeAssets> إليها . اتضح مثل هذا:
<PackageReference Include="ModPlus.Revit.API.2015"> <Version>1.0.0</Version> <ExcludeAssets>runtime</ExcludeAssets> </PackageReference>
الآن ، عند إنشاء مشروع ، لن يتم نسخ الملفات من الحزمة إلى مجلد الإخراج.
نذهب إلى أبعد من ذلك - تخيل على الفور أن المكون الإضافي الخاص بنا سوف يستخدم شيئًا ما من واجهة برمجة تطبيقات Revit ، والتي تغيرت مع إصدار إصدارات جديدة. حسنًا ، أو فقط ، نحتاج إلى تغيير شيء ما في الكود ، اعتمادًا على إصدار Revit الذي نصنع المكون الإضافي له. لحل هذه الاختلافات في التعليمات البرمجية ، سوف نستخدم رموز الترجمة الشرطية. افتح خصائص المشروع ، انتقل إلى علامة التبويب " التجميع " وفي حقل " رموز التجميع الشرطي " ، اكتب R2015 .

لاحظ أنه يجب إضافة الرمز لكل من تكوين Debug وتكوين الإصدار.
حسنًا ، أثناء وجودنا في نافذة الخصائص ، ننتقل على الفور إلى علامة التبويب " التطبيق " وفي الحقل " مساحة الاسم الافتراضية " نحذف اللاحقة _2015 حتى تصبح مساحة اسمنا عالمية ومستقلة عن اسم التجميع:

في حالتي ، في المنتج النهائي ، يتم وضع المكونات الإضافية لجميع الإصدارات في مجلد واحد ، لذلك تظل أسماء التجميع الخاصة بي مع لاحقة النموذج _20xx . ولكن يمكنك أيضًا إزالة اللاحقة من اسم التجميع إذا كان موقع الملفات في مجلدات مختلفة مفترضًا.
نمرر إلى رمز الملف Class1.cs ونحاكي بعض التعليمات البرمجية هناك ، مع مراعاة الإصدارات المختلفة من 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; } } }
أخذت على الفور في الاعتبار جميع إصدارات Revit أعلى من إصدار 2015 (التي كانت في وقت كتابة هذا التقرير) وأخذت على الفور في الاعتبار وجود رموز الترجمة الشرطية ، التي أقوم بإنشائها باستخدام نفس القالب.
نمر إلى تسليط الضوء الرئيسي. نقوم بإنشاء مشروع جديد في حلنا ، فقط لإصدار المكون الإضافي لـ Revit 2016. نكرر جميع الخطوات الموضحة أعلاه ، على التوالي ، مع استبدال الرقم 2015 بالرقم 2016. لكننا نحذف ملف Class1.cs من المشروع الجديد.

الملف الذي يحتوي على الكود المطلوب - Class1.cs - لدينا بالفعل ونحتاج فقط إلى إدراج رابط إليه في المشروع الجديد. هناك طريقتان لإدراج الروابط:
- منذ فترة طويلة - انقر فوق المشروع باستخدام زر الماوس الأيمن ، وحدد العنصر " إضافة " -> " عنصر موجود " ، في النافذة التي تفتح ، ابحث عن الملف المطلوب ، وبدلاً من خيار " إضافة " ، حدد خيار " إضافة رابط "

- باختصار - في مستكشف الحلول ، حدد الملف المطلوب (أو حتى الملفات. أو حتى المجلدات بأكملها) واسحب وإفلات في المشروع الجديد مع الضغط على مفتاح Alt. عند السحب ، سترى أنه عندما تضغط على المفتاح Alt ، فإن المؤشر على الماوس سيتغير من علامة الجمع إلى السهم.
محدث: لقد ارتكبت بعض التشويش في هذا القسم - لنقل عدة ملفات ، مع الاستمرار على Shift + Alt !
بعد الإجراء ، سنرى في المشروع الثاني ملف Class1.cs مع الأيقونة المقابلة (السهم الأزرق):

عند تحرير الكود في نافذة المحرر ، يمكنك أيضًا الاختيار في سياق أي مشروع لعرض الكود ، والذي يسمح لك بمشاهدة الكود الذي يتم تحريره برموز مختلفة للتجميع الشرطي:

بموجب هذا المخطط ، نقوم بإنشاء جميع المشاريع الأخرى (2017-2020). اختراق الحياة - إذا قمت بسحب وإفلات الملفات في مستكشف الحلول ليس من المشروع الأساسي ، ولكن من المشروع حيث تم إدراجها بالفعل كرابط ، فلا يمكنك الضغط باستمرار على مفتاح Alt!
يعد الخيار الموضح جيدًا حتى يتم إضافة الإصدار الجديد من المكون الإضافي أو حتى تتم إضافة الملفات الجديدة إلى المشروع - يصبح كل هذا كئيباً للغاية. ومؤخراً ، أدركت فجأة كيفية حل كل هذا بمشروع واحد ونحن نتحرك إلى الطريقة الثانية
سحر التكوين
بعد القراءة هنا ، يمكنك أن تصيح ، "ماذا بحق الجحيم هل وصفت الطريقة الأولى ، إذا كانت المقالة على الفور عن الثانية؟!" وقد وصفت كل شيء لجعله أكثر وضوحًا لماذا نحتاج إلى رموز تجميع مشروط وفي أي الأماكن تختلف مشاريعنا. والآن أصبح الأمر أكثر وضوحًا بالنسبة لنا عن الفروق المحددة في المشروع التي نحتاج إلى تنفيذها ، ولم يتبق سوى مشروع واحد.
ولكي يكون كل شيء أكثر وضوحًا ، فلن ننشئ مشروعًا جديدًا ، بل سنجري تغييرات على مشروعنا الحالي ، الذي تم إنشاؤه بالطريقة الأولى.
أولاً وقبل كل شيء ، نزيل جميع المشاريع من الحل ، باستثناء المشروع الرئيسي (الذي يحتوي على الملفات مباشرة). أي مشاريع للإصدارات 2016-2020. افتح مجلد الحل واحذف مجلدات هذه المشروعات هناك.
لدينا حل واحد متبقي في الحل - MySuperPluginForRevit_2015 . نفتح خصائصه و:
- في علامة تبويب التطبيق ، قم بإزالة اللاحقة _2015 من اسم التجميع (سيصبح السبب واضحًا)
- في علامة التبويب " التجميع " ، احذف رمز الترجمة الشرطية R2015 من الحقل المقابل
ملاحظة: في أحدث إصدار من Visual Studio ، هناك رموز تجميع مشروط لا يتم عرضها في نافذة خصائص المشروع ، على الرغم من وجودها. إذا كان لديك هذا الخلل ، فأنت بحاجة إلى إزالتها يدويًا من ملف .csproj. ومع ذلك ، ما زلنا نعمل فيه ، لذا تابع القراءة.
أعد تسمية المشروع في نافذة مستكشف الحلول عن طريق إزالة اللاحقة _2015 ثم قم بإزالة المشروع من الحل. هذا ضروري للحفاظ على النظام ومشاعر الكمال! نفتح مجلد حلنا ، ونعيد تسمية مجلد المشروع هناك بنفس الطريقة ونعيد تحميل المشروع مرة أخرى إلى الحل.
افتح مدير التهيئة. نحن ، من حيث المبدأ ، لن نحتاج إلى تهيئة الإصدار ، لذلك نقوم بحذفه. نقوم بإنشاء تكوينات جديدة بأسماء R2015 ، R2016 ، ... ، R2020 مألوفة لنا بالفعل. يرجى ملاحظة أنك لا تحتاج إلى نسخ المعلمات من التكوينات الأخرى ولا تحتاج إلى إنشاء تكوينات المشروع:

نذهب إلى مجلد المشروع ونفتح الملف بالملحق .csproj في محرر مناسب. بالمناسبة ، يمكن أيضًا فتحه في Visual Studio - تحتاج إلى إلغاء تحميل المشروع وبعد ذلك سيكون العنصر المناسب في قائمة السياق:

يعد التحرير في Visual Studio هو الأفضل ، حيث أن المحرر يحاذي ويطالبك.
في الملف ، سنرى عناصر PropertyGroup - في الأعلى هو عام ، ثم مع الشروط. تقوم هذه العناصر بتعيين خصائص المشروع أثناء التجميع. العنصر الأول ، الذي بدون شروط ، يحدد الخصائص العامة ، والعناصر ذات الشروط ، على التوالي ، يغير بعض الخصائص حسب التكوينات.
نذهب إلى العنصر (الأول) العام في PropertyGroup وننظر إلى خاصية AssemblyName - هذا هو اسم التجميع وينبغي أن يكون لدينا بدون اللاحقة _2015 . إذا كان هناك لاحقة ، فاحذفها.
نجد عنصرا مع الشرط
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
نحن لسنا في حاجة إليها - نحن نحذفها.
شرط الشرط
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
سيكون من الضروري للعمل في مرحلة تطوير وتصحيح التعليمات البرمجية. يمكنك تغيير خصائصها حسب احتياجاتك - تعيين مسارات إخراج مختلفة ، وتغيير رموز الترجمة الشرطية ، إلخ.
الآن قم بإنشاء عناصر PropertyGroup جديدة لتكويناتنا. في هذه العناصر ، نحتاج فقط إلى تعيين أربعة خصائص:
- OutputPath هو مجلد الإخراج. قمت بتعيين bin \ R20xx القيمة القياسية
- DefineConstants - رموز التجميع الشرطي. ضبط TRACE ؛ R20xx
- TargetFrameworkVersion - إصدار النظام الأساسي. بالنسبة للإصدارات المختلفة من واجهة برمجة تطبيقات Revit ، يجب تحديد منصات مختلفة.
- اسم التجميع - اسم التجميع (أي اسم الملف). يمكنك كتابة اسم التجميع المطلوب مباشرةً ، ولكن بالنسبة إلى العالمية ، أوصي بكتابة قيمة $ (AssemblyName) _20xx . للقيام بذلك ، سبق أن أزلنا اللاحقة من اسم التجميع
الميزة الأكثر أهمية لكل هذه العناصر هي أنه يمكن نسخها بشكل تافه إلى مشاريع أخرى دون تغييرها على الإطلاق. في وقت لاحق من هذه المقالة سوف أرفق جميع محتويات ملف .csproj.
حسنًا ، اكتشفنا خصائص المشروع - إنه ليس بالأمر الصعب. ولكن ماذا تفعل مع مكتبات المكونات (حزم NuGet). إذا نظرنا إلى أبعد من ذلك ، فسنرى أن مكتبات المكونات الإضافية محددة بواسطة عناصر ItemGroup . ولكن هذا هو الحظ السيئ - يعالج هذا العنصر بشكل غير صحيح الظروف ، مثل عنصر PropertyGroup . ربما يكون هذا خلل في Visual Studio ، ولكن إذا قمت بتعيين العديد من عناصر ItemGroup مع شروط التكوين ، وأدرجت روابط مختلفة إلى حزم NuGet بالداخل ، ثم عند تغيير التكوين ، يتم توصيل جميع الحزم المحددة بالمشروع.
يأتي عنصر " اختيار" في مساعدتنا ، والذي يعمل وفقًا للمنطق المعتاد.
باستخدام عنصر اختيار ، نقوم بتعريف حزم NuGet المختلفة لتكوينات مختلفة:
جميع محتويات csproj <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">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>bin\Debug\</OutputPath> <DefineConstants>DEBUG;R2015</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2015|AnyCPU' "> <OutputPath>bin\R2015\</OutputPath> <DefineConstants>TRACE;R2015</DefineConstants> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <AssemblyName>$(AssemblyName)_2015</AssemblyName> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2016|AnyCPU' "> <OutputPath>bin\R2016\</OutputPath> <DefineConstants>TRACE;R2016</DefineConstants> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <AssemblyName>$(AssemblyName)_2016</AssemblyName> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2017|AnyCPU' "> <OutputPath>bin\R2017\</OutputPath> <DefineConstants>TRACE;R2017</DefineConstants> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <AssemblyName>$(AssemblyName)_2017</AssemblyName> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2018|AnyCPU' "> <OutputPath>bin\R2018\</OutputPath> <DefineConstants>TRACE;R2018</DefineConstants> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <AssemblyName>$(AssemblyName)_2018</AssemblyName> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2019|AnyCPU' "> <OutputPath>bin\R2019\</OutputPath> <DefineConstants>TRACE;R2019</DefineConstants> <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> <AssemblyName>$(AssemblyName)_2019</AssemblyName> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'R2020|AnyCPU' "> <OutputPath>bin\R2020\</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="Properties\AssemblyInfo.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>
يرجى ملاحظة أنه في أحد الشروط ، حددت تكوينين عبر OR (أو) . وبالتالي ، سيتم توصيل الحزمة الضرورية أثناء تكوين Debug .
وهنا لدينا تقريبا كل شيء مثالي. نقوم بإعادة تشغيل المشروع ، وتشغيل التهيئة التي نحتاجها ، واستدعاء عنصر " استعادة جميع حزم NuGet " في قائمة سياق الحل (وليس المشروع) ونرى كيف تتغير الحزم.

وفي هذه المرحلة وصلت إلى طريق مسدود - من أجل جمع كل التكوينات في وقت واحد ، يمكننا استخدام مجموعة الدُفعات (قائمة " التجميع " -> " تجميع الدُفعات ") ، ولكن عند تبديل التكوينات ، لا تتم استعادة الحزم تلقائيًا. وعند تجميع المشروع ، لا يحدث ذلك أيضًا ، رغم أنه من الناحية النظرية ، يجب أن يحدث. لم أجد حلاً لهذه المشكلة بالوسائل القياسية. وعلى الأرجح هذا أيضًا خطأ في Visual Studio.
لذلك ، للتجميع الدفعي ، تقرر استخدام نظام التجميع الآلي Nuke الخاص. في الواقع ، لم أكن أرغب في ذلك ، لأنني اعتبر ذلك غير ضروري في إطار تطوير المكونات الإضافية ، لكن في الوقت الحالي لا أرى أي حل آخر. والسؤال "لماذا بالضبط النووي؟" الجواب بسيط - نحن استخدامه في العمل.
لذا ، انتقل إلى مجلد حلنا (وليس المشروع) ، اضغط مع الاستمرار على مفتاح Shift وانقر بزر الماوس الأيمن على مكان فارغ في المجلد - في قائمة السياق ، حدد العنصر " Open PowerShell window هنا ".

إذا لم تكن مثبتة على السلاح النووي ، فاكتب الأمر أولاً
dotnet tool install Nuke.GlobalTool –global
الآن اكتب الأمر nuke وسيُطلب منك تكوين nuke للمشروع الحالي. لا أعرف كيفية كتابتها بشكل صحيح باللغة الروسية - تعذر العثور. سيتم كتابة ملف nuke باللغة الإنجليزية. هل تريد إعداد بناء؟ [ص / ن]
اضغط على المفتاح Y ومن ثم سيكون هناك الإعدادات الفورية. نحتاج إلى أبسط خيار باستخدام MSBuild ، لذلك نجيب كما في لقطة الشاشة:

دعنا ننتقل إلى Visual Studio ، والذي سيوفر لنا إعادة تحميل الحل ، حيث تمت إضافة مشروع جديد إليه. نحن نعيد تشغيل الحل ونرى أن لدينا مشروع بناء لا نهتم إلا بملف واحد - Build.cs

افتح هذا الملف واكتب نصًا لإنشاء المشروع لجميع التكوينات. حسنًا ، أو استخدم البرنامج النصي الخاص بي ، والذي يمكنك تعديله بنفسك:
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;
نعود إلى نافذة PowerShell ونكتب الأمر nuke مرة أخرى (يمكنك كتابة الأمر nuke باستخدام الهدف المطلوب. لكن لدينا هدفًا واحدًا يبدأ افتراضيًا). بعد الضغط على مفتاح Enter ، سنشعر بأننا متسللين حقيقيين ، لأنه كما في فيلم ، سيتم تجميع مشروعنا تلقائيًا لتكوينات مختلفة.
بالمناسبة ، يمكنك استخدام PowerShell مباشرة من Visual Studio (القائمة " عرض " -> " نوافذ أخرى " -> " Package Manager Console ") ، ولكن سيكون كل شيء أبيض وأسود ، وهو غير مناسب للغاية.
في هذا مقالي انتهى. أنا متأكد من أنه يمكنك معرفة خيار أوتوكاد بنفسك. آمل أن تجد المواد المعروضة هنا "زبائنها".
شكرا لاهتمامكم!