إرجاع Thread.Abort () إلى .NET Core. تسليم التطبيق مع نسخته من CoreCLR و CoreFX

عند الترحيل من .NET Framework إلى .NET Core ، قد تأتي بعض اللحظات غير السارة. على سبيل المثال ، إذا كان التطبيق الخاص بك يستخدم المجالات ، فسيتعين عليك إعادة كتابة المنطق. موقف مشابه مع Thread.Abort () : تعجب شركة Microsoft من خلال هذه الممارسة (وهي محقة في ذلك) لدرجة أنها أعلنت لأول مرة أن هذه الطريقة قد تم إهمالها ، ثم قامت بقصها تمامًا عن الإطار وأصبحت الآن ترتكز على PlatformNotSupportedException .

ولكن ماذا لو كان تطبيقك يستخدم Thread.Abort () ، وترغب حقًا في ترجمته إلى .NET Core دون إعادة كتابة أي شيء؟ حسنًا ، نعلم جيدًا أن النظام الأساسي يدعم هذه الوظيفة ، لذا يمكنني إرضائك: هناك طريقة للخروج ، تحتاج فقط إلى تجميع نسختك من CLR .

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



تم تحقيق ذلك بفضل شيئين: رغبة Microsoft في .NET Core عبر الأنظمة الأساسية والعمل الذي أنجزه المطورون لنقل الشفرة المصدرية لإطار العمل لفتح الوصول. دعنا نستفيد من هذا.

الحد الأدنى النظري:

  • يتيح لنا نشر dotnet نشر تطبيق قائم بذاته : سيتم تسليم الإطار معه ، ولن يتم البحث فيه في مكان ما في GAC
  • يمكن تعيين إصدار CoreCLR الذي سيتم تشغيل التطبيق عليه ، في ظل ظروف معينة ، باستخدام runtimeconfig.json
  • يمكننا بناء CoreFX الخاص بنا: github.com/dotnet/corefx
  • يمكننا بناء CoreCLR الخاصة بنا : github.com/dotnet/coreclr

تخصيص CoreFX


قبل الانتقال إلى هدفنا الرئيسي - إرجاع Thread.Abort ( ) - لنغير شيئًا أساسيًا في CoreFX لتسخينه لاختبار وظائف جميع الأدوات. على سبيل المثال ، على خطى مقالتي السابقة حول الديناميكي ، نحن نمنع تمامًا استخدامه في التطبيق. لماذا؟ لأننا نستطيع.

المتطلبات الأساسية


بادئ ذي بدء ، سنقوم بتثبيت كل ما هو ضروري للتجميع:

  • CMake
  • مرئي ستوديو 2019 معاينة
  • أحدث إصدار من .NET Core SDK (معاينة .NET Core 3.0)

Visual Studio 2019 - أعباء العمل


تطوير سطح المكتب. NET

  • جميع المكونات المطلوبة
  • .NET Framework 4.7.2 أدوات التطوير

تطوير سطح المكتب مع C ++

  • جميع المكونات المطلوبة
  • مجموعة أدوات VC ++ 2019 v142 (x 86 ، x64)
  • Windows 8.1 SDK و UCRT SDK
  • مجموعة أدوات VC ++ 2017 v141 (x86 ، x64)

تطوير .NET Core عبر الأنظمة الأساسية

  • جميع المكونات المطلوبة

Visual Studio 2019 - مكونات فردية


  • C # و Visual Basic Roslyn المجمعين
  • أدوات التحليل الثابت
  • حزمة استهداف المكتبة المحمولة .NET
  • Windows 10 SDK أو Windows 8.1 SDK
  • Visual Studio C ++ الميزات الأساسية
  • مجموعة أدوات VC ++ 2019 v142 (x 86 ، x64)
  • مجموعة أدوات VC ++ 2017 v141 (x86 ، x64)
  • MSBuild
  • .NET Framework 4.7.2 حزمة الاستهداف
  • ويندوز العالمي CRT SDK

استنساخ corefx :

git clone https://github.com/dotnet/corefx.git 

الآن تعطيل ديناميكية . سنفتح هذا (سأشير فيما يلي إلى المسارات المتعلقة بجذر المستودع)

 corefx\src\System.Linq.Expressions\src\System\Runtime\CompilerServices\CallSite.cs 

وفي نهاية وظيفة CallSite <T> .Create ، أدخل الكود العادي:

 throw new PlatformNotSupportedException("No way"); 

نعود إلى corefx وتنفيذ build.cmd . بعد اكتمال التجميع ، قم بإنشاء مشروع .NET Core جديد في Visual Studio بالمحتويات التالية:

 public int Test { get; set; } public static void Main(string[] args) { try { dynamic a = new Program(); a.Test = 120; } catch (Exception e) { Console.WriteLine(e); } //,    foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { Console.WriteLine(asm.Location); } } 

نحن تجميع مشروعنا. اذهب الآن إلى

 corefx\artifacts\packages\Debug\NonShipping 

ونجد هناك حزمة تبدو مثل هذا: Microsoft.Private.CoreFx.NETCoreApp. 5.0.0-dev.19465.1 .nupkg . نفتح .csproj لمشروعنا وأدخل الأسطر التالية هناك:

 <PropertyGroup> <PackageConflictPreferredPackages>Microsoft.Private.CoreFx.NETCoreApp;runtime.$(RuntimeIdentifiers).Microsoft.Private.CoreFx.NETCoreApp;$(PackageConflictPreferredPackages)</PackageConflictPreferredPackages> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Private.CoreFx.NETCoreApp" Version="5.0.0-dev.19465.1" /> </ItemGroup> 

يجب أن يكون الإصدار هو نفسه كما في اسم الحزمة المجمعة. في حالتي ، 5.0.0-dev.19465.1 .



انتقل إلى إعدادات nuget لمشروعنا وأضف مسارين جديدين هناك:

 corefx\artifacts\packages\Debug\NonShipping corefx\artifacts\packages\Debug\Shipping 

وإلغاء جميع الآخرين.



انتقل إلى مجلد المشروع وتنفيذه

 dotnet publish --runtime win-x64 --self-contained 

القيام به! يبقى فقط لتشغيل:



إنه يعمل! لا تؤخذ المكتبات من GAC ، ولا تعمل ديناميكية .

جعل CoreCLR العظمى مرة أخرى


الآن دعنا ننتقل إلى الجزء الثاني ، ونعود إلى Thread.Abort () . هناك مفاجأة غير سارة تنتظرنا هنا: يكمن تنفيذ مؤشر الترابط في CoreCLR ، وهو ليس جزءًا من CoreFX ويتم تثبيته مسبقًا على الجهاز بشكل منفصل. أولاً ، قم بإنشاء مشروع تجريبي:

 var runtimeInformation = RuntimeInformation.FrameworkDescription; Console.WriteLine(runtimeInformation); var thr = new Thread(() => { try { while (true) { Console.WriteLine("."); Thread.Sleep(500); } } catch (ThreadAbortException) { Console.WriteLine("Thread aborted!"); } }); foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { Console.WriteLine(asm.Location); } thr.Start(); Thread.Sleep(2000); thr.Abort(); 

فرغ coreclr . العثور على الملف

 coreclr\src\System.Private.CoreLib\shared\System\Threading\Thread.cs 

واستبدل إحباط () بـ

 [SecuritySafeCritical] [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public void Abort() { AbortInternal(); } [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void AbortInternal(); 

نحن الآن بحاجة إلى إرجاع السمات وتنفيذ c ++ . قمت بجمعها على شكل قطع من مستودعات مختلفة مفتوحة من .NET Framework ولأغراض الراحة صممت كل التغييرات في شكل طلب سحب .

ملاحظة: عند البناء ، كانت هناك مشاكل في الموارد في السمات "الجديدة" ، والتي أنا
"ثابت" مع المقابس. ضع ذلك في الاعتبار إذا كنت تريد استخدام هذا الرمز في أي مكان آخر غير التجربة المنزلية.

بعد دمج هذه التغييرات في الكود ، قم بتشغيل build.cmd من coreclr . قد يبدأ التجميع في المراحل اللاحقة في الرش مع الأخطاء ، لكنه ليس مخيفًا ، الشيء الرئيسي بالنسبة لنا هو أن CoreCLR يمكنه التجميع. سوف تكمن في:

 coreclr\bin\Product\Windows_NT.x64.Debug 

طريقة سهلة


نقوم بها

 dotnet publish --runtime win-x64 --self-contained 

يتم إسقاط الملفات من Windows_NT.x64.Debug في المجلد مع التطبيق المنشور.

الطريق الصعب


بمجرد تجميع المكتبات ، انتقل إلى

 C:\Program Files\dotnet\shared\Microsoft.NETCore.App 

واستنساخ المجلد 3.0.0. سوف نسميها ، على سبيل المثال ، 5.0.1. نقوم بنسخ كل شيء موجود في Windows_NT.x64.Debug ، باستثناء المجلدات. الآن لدينا نسخة من CoreCLR ستكون متاحة من خلال runtimeconfig.

وضع مشروعنا معا. أضف إلى .csproj :

 <PropertyGroup> <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> <PackageConflictPreferredPackages>Microsoft.Private.CoreFx.NETCoreApp;runtime.$(RuntimeIdentifiers).Microsoft.Private.CoreFx.NETCoreApp;$(PackageConflictPreferredPackages)</PackageConflictPreferredPackages> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Private.CoreFx.NETCoreApp" Version="5.0.0-dev.19465.1" /> </ItemGroup> 

نكرر التلاعب مع nuget من الجزء السابق من المقال. ننشر

 dotnet publish --runtime win-x64 --self-contained 

في runtimeconfig.json ، أدخل التكوين التالي:

 { "runtimeOptions": { "tfm": "netcoreapp3.0", "framework": { "name": "Microsoft.NETCore.App", "version": "5.0.1" } } } 

يؤدي


تشغيل!



حدث السحر. الآن في تطبيقات .NET Core ، يعمل Thread.Abort () مرة أخرى. ولكن ، بالطبع ، فقط على ويندوز .

Source: https://habr.com/ru/post/ar467475/


All Articles