Kembalikan Thread.Abort () ke .NET Core. Pengiriman aplikasi dengan versi CoreCLR dan CoreFX

Saat bermigrasi dari .NET Framework ke .NET Core , beberapa momen tidak menyenangkan mungkin muncul. Misalnya, jika aplikasi Anda menggunakan domain, Anda harus menulis ulang logikanya. Situasi yang serupa dengan Thread.Abort () : Microsoft sangat tidak disukai oleh praktik ini (dan memang demikian) bahwa mereka pertama kali menyatakan metode ini sudah usang , dan kemudian benar-benar memotongnya keluar dari kerangka kerja dan sekarang dengan berbahaya melempar PlatformNotSupportedException .

Tetapi bagaimana jika aplikasi Anda menggunakan Thread.Abort () , dan Anda benar - benar ingin menerjemahkannya ke .NET Core tanpa menulis ulang apa pun? Yah, kami tahu betul bahwa platform bahkan mendukung fungsi ini, jadi saya bisa menyenangkan Anda: ada jalan keluar, Anda hanya perlu merakit versi CLR Anda sendiri.

Penafian: Ini adalah artikel yang sepenuhnya praktis dengan teori minimum, yang dirancang hanya untuk menunjukkan pilihan baru untuk interaksi antara pengembang dan lingkungan .NET. Jangan pernah melakukan ini dalam produksi. Tetapi jika Anda benar-benar ingin ...



Ini dimungkinkan berkat dua hal: keinginan Microsoft untuk cross-platform .NET Core dan pekerjaan yang dilakukan oleh pengembang untuk mentransfer kode sumber kerangka kerja untuk membuka akses. Mari manfaatkan ini.

Minimum teoritis:

  • mempublikasikan dotnet memungkinkan kita untuk mempublikasikan aplikasi mandiri : kerangka kerja akan dikirimkan bersamanya, dan tidak mencari di suatu tempat di GAC
  • Versi CoreCLR di mana aplikasi akan berjalan, dalam kondisi tertentu, dapat diatur menggunakan runtimeconfig.json
  • Kita dapat membangun CoreFX kita sendiri: github.com/dotnet/corefx
  • Kita dapat membangun CoreCLR kita sendiri: github.com/dotnet/coreclr

Kustomisasi CoreFX


Sebelum beralih ke tujuan utama kami - mengembalikan Thread.Abort ( ) - mari kita ubah sesuatu yang mendasar di CoreFX untuk pemanasan untuk menguji fungsionalitas semua alat. Sebagai contoh, dalam jejak artikel saya sebelumnya tentang dinamis , kami sepenuhnya melarang penggunaannya dalam aplikasi. Mengapa Karena kita bisa.

Prasyarat


Pertama-tama, kami akan menginstal semua yang diperlukan untuk perakitan:

  • CMake
  • Visual Studio 2019 Pratinjau
  • .NET Core SDK terbaru (.NET Core 3.0 Preview)

Visual Studio 2019 - Beban Kerja


Pengembangan desktop .NET

  • Semua Komponen yang Diperlukan
  • .NET Framework 4.7.2 Alat Pengembangan

Pengembangan desktop dengan C ++

  • Semua Komponen yang Diperlukan
  • Toolset VC ++ 2019 v142 (x86, x64)
  • Windows 8.1 SDK dan UCRT SDK
  • Toolset VC ++ 2017 v141 (x86, x64)

.NET Core pengembangan lintas platform

  • Semua Komponen yang Diperlukan

Visual Studio 2019 - Komponen individual


  • C # dan Visual Basic Roslyn Compiler
  • Alat Analisis Statis
  • .NET Portable Library Targeting Pack
  • Windows 10 SDK atau Windows 8.1 SDK
  • Visual Studio C ++ Fitur Inti
  • Toolset VC ++ 2019 v142 (x86, x64)
  • Toolset VC ++ 2017 v141 (x86, x64)
  • Msbuild
  • .NET Framework 4.7.2 Paket Penargetan
  • Windows Universal CRT SDK

Klon corefx :

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

Sekarang nonaktifkan dinamis . Kami akan terbuka untuk ini (selanjutnya saya akan menunjukkan jalur relatif ke akar repositori)

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

Dan di akhir fungsi CallSite <T> .Create, masukkan kode biasa:

 throw new PlatformNotSupportedException("No way"); 

Kami kembali ke corefx dan menjalankan build.cmd . Setelah perakitan selesai, buat proyek .NET Core baru di Visual Studio dengan konten berikut:

 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); } } 

Kami menyusun proyek kami. Sekarang pergilah ke

 corefx\artifacts\packages\Debug\NonShipping 

dan kami menemukan ada paket yang terlihat seperti ini: Microsoft.Private.CoreFx.NETCoreApp. 5.0.0-dev.19465.1 .nupkg . Kami membuka .csproj proyek kami dan menyisipkan baris berikut di sana:

 <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> 

Versi harus sama dengan nama paket yang dirakit. Dalam kasus saya, 5.0.0-dev.19465.1 .



Buka pengaturan nuget untuk proyek kami dan tambahkan dua jalur baru di sana:

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

Dan hapus centang semua yang lain.



Buka folder proyek dan jalankan

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

Selesai! Tetap berjalan:



Itu berhasil! Perpustakaan tidak diambil dari GAC , dinamis tidak berfungsi.

Buat CoreCLR Hebat Lagi


Sekarang mari kita beralih ke bagian kedua, mengembalikan Thread.Abort () . Kejutan yang tidak menyenangkan menunggu kita di sini: Implementasi utas terletak pada CoreCLR , yang bukan bagian dari CoreFX dan sudah diinstal sebelumnya pada mesin secara terpisah. Pertama, buat proyek demo:

 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(); 

Mengempiskan coreclr . Temukan file

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

Dan ganti Abort () dengan

 [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(); 

Sekarang kita perlu mengembalikan atribut dan implementasi c ++ . Saya mengumpulkannya dalam beberapa bagian dari berbagai repositori terbuka .NET Framework dan untuk kenyamanan saya merancang semua perubahan dalam bentuk permintaan tarik .

Catatan: saat membangun, ada masalah dengan sumber daya di atribut "baru", yang saya
"Tetap" dengan colokan. Ingatlah hal ini jika Anda ingin menggunakan kode ini di mana pun selain eksperimen di rumah.

Setelah mengintegrasikan perubahan ini ke dalam kode, jalankan build.cmd dari coreclr . Perakitan pada tahap selanjutnya mungkin mulai menaburkan kesalahan, tapi itu tidak menakutkan, hal utama bagi kami adalah bahwa CoreCLR dapat berkumpul. Itu akan terletak di:

 coreclr\bin\Product\Windows_NT.x64.Debug 

Cara mudah


Kami melakukan

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

File dari Windows_NT.x64.Debug dijatuhkan ke folder dengan aplikasi yang diterbitkan.

Cara yang sulit


Setelah perpustakaan dirakit, buka

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

dan mengkloning folder 3.0.0. Kami akan menyebutnya, misalnya, 5.0.1. Kami menyalin semua yang ada di Windows_NT.x64.Debug , kecuali foldernya. Sekarang versi CoreCLR kami akan tersedia melalui runtimeconfig.

Menyatukan proyek kami. Tambahkan ke .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> 

Kami mengulangi manipulasi dengan nuget dari bagian artikel sebelumnya. Terbitkan

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

Di runtimeconfig.json, masukkan konfigurasi berikut:

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

Hasil


Luncurkan!



Keajaiban itu terjadi. Sekarang di aplikasi .NET Core kami Thread.Abort () berjalan kembali. Tapi, tentu saja, hanya di Windows .

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


All Articles