عند الترحيل من
.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); }
نحن تجميع مشروعنا. اذهب الآن إلى
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]
نحن الآن بحاجة إلى إرجاع السمات وتنفيذ
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 () مرة أخرى. ولكن ، بالطبع ، فقط على
ويندوز .