Bei der Migration von
.NET Framework auf
.NET Core können einige unangenehme Momente auftreten. Wenn Ihre Anwendung beispielsweise Domänen verwendet, müssen Sie die Logik neu schreiben. Eine ähnliche Situation mit
Thread.Abort () :
Microsoft ist von dieser Vorgehensweise (und das zu Recht) so
unzufrieden, dass sie diese Methode zuerst für
veraltet erklärt und dann vollständig aus dem Framework herausgeschnitten haben. Jetzt wird auf verräterische Weise eine
PlatformNotSupportedException ausgelöst .
Aber was ist, wenn Ihre Anwendung
Thread.Abort () verwendet und Sie sie
wirklich in
.NET Core übersetzen möchten, ohne etwas neu zu schreiben? Wir wissen sehr gut, dass die Plattform diese Funktionalität sogar unterstützt, daher kann ich Ihnen gefallen: Es gibt einen Ausweg, Sie müssen nur Ihre eigene Version der
CLR zusammenstellen .
Haftungsausschluss: Dies ist ein rein praktischer Artikel mit einem Minimum an Theorie, der nur neue Optionen für die Interaktion zwischen dem Entwickler und der .NET-Umgebung demonstrieren soll. Mach das niemals in der Produktion. Aber wenn du wirklich willst ...
Möglich wurde dies durch zwei Dinge:
Microsofts Wunsch nach plattformübergreifendem
.NET Core und die Arbeit der Entwickler, den Quellcode des Frameworks auf Open Access zu übertragen. Lassen Sie uns dies ausnutzen.
Theoretisches Minimum:
- Mit dotnet Publish können wir eigenständige Anwendungen veröffentlichen: Das Framework wird mitgeliefert und nicht irgendwo im GAC durchsucht
- Die Version von CoreCLR, auf der die Anwendung unter bestimmten Bedingungen ausgeführt wird, kann mit runtimeconfig.json festgelegt werden
- Wir können unser eigenes CoreFX erstellen : github.com/dotnet/corefx
- Wir können unsere eigene CoreCLR erstellen: github.com/dotnet/coreclr
Passen Sie CoreFX an
Bevor wir zu unserem Hauptziel
übergehen -
Thread.Abort ( ) zurückzugeben - ändern wir etwas Grundlegendes in
CoreFX , um die Funktionalität aller Tools zu testen. In den Fußstapfen meines
vorherigen Artikels über
Dynamik verbieten wir beispielsweise die Verwendung in der Anwendung vollständig. Warum? Weil wir können.
Voraussetzungen
Zunächst installieren wir
alles, was für die Montage
erforderlich ist :
- CMake
- Visual Studio 2019 Vorschau
- Neuestes .NET Core SDK (Vorschau auf .NET Core 3.0)
Visual Studio 2019 - Workloads
.NET Desktop-Entwicklung- Alle erforderlichen Komponenten
- .NET Framework 4.7.2 Entwicklungstools
Desktop-Entwicklung mit C ++- Alle erforderlichen Komponenten
- VC ++ 2019 v142 Toolset (x86, x64)
- Windows 8.1 SDK und UCRT SDK
- VC ++ 2017 v141 Toolset (x86, x64)
Plattformübergreifende .NET Core-Entwicklung- Alle erforderlichen Komponenten
Visual Studio 2019 - Einzelne Komponenten
- C # und Visual Basic Roslyn Compiler
- Statische Analysewerkzeuge
- Targeting Pack für tragbare .NET-Bibliotheken
- Windows 10 SDK oder Windows 8.1 SDK
- Visual Studio C ++ - Kernfunktionen
- VC ++ 2019 v142 Toolset (x86, x64)
- VC ++ 2017 v141 Toolset (x86, x64)
- Msbuild
- .NET Framework 4.7.2 Targeting Pack
- Windows Universal CRT SDK
Klone corefx :
git clone https://github.com/dotnet/corefx.git
Deaktivieren Sie jetzt die
Dynamik . Wir werden uns dafür öffnen (im Folgenden werde ich die Pfade relativ zum Stammverzeichnis des Repositorys angeben.)
corefx\src\System.Linq.Expressions\src\System\Runtime\CompilerServices\CallSite.cs
Fügen Sie am Ende der
CallSite <T>
.Create-Funktion den einfachen Code ein:
throw new PlatformNotSupportedException("No way");
Wir kehren zu
corefx zurück und führen
build.cmd aus . Erstellen Sie nach Abschluss der Assembly ein neues
.NET Core- Projekt in
Visual Studio mit den folgenden Inhalten:
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); }
Wir stellen unser Projekt zusammen. Jetzt geh zu
corefx\artifacts\packages\Debug\NonShipping
und wir finden dort ein Paket, das ungefähr so aussieht:
Microsoft.Private.CoreFx.NETCoreApp. 5.0.0-dev.19465.1 .nupkg . Wir öffnen
.csproj unseres Projekts und fügen dort die folgenden Zeilen ein:
<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>
Die Version sollte mit der im Namen des zusammengestellten Pakets übereinstimmen. In meinem Fall
5.0.0-dev.19465.1 .

Gehen Sie zu den
Nuget- Einstellungen für unser Projekt und fügen Sie dort zwei neue Pfade hinzu:
corefx\artifacts\packages\Debug\NonShipping corefx\artifacts\packages\Debug\Shipping
Und deaktivieren Sie alle anderen.

Gehen Sie zum Projektordner und führen Sie ihn aus
dotnet publish --runtime win-x64 --self-contained
Fertig! Es bleibt nur zu laufen:

Es funktioniert! Bibliotheken werden nicht aus dem
GAC entnommen,
Dynamik funktioniert nicht.
Machen Sie CoreCLR wieder großartig
Fahren wir nun mit dem zweiten Teil fort und geben
Thread.Abort () zurück . Hier erwartet uns eine unangenehme Überraschung: Die
Thread- Implementierung liegt in
CoreCLR , das nicht Teil von
CoreFX ist und separat auf dem Computer
vorinstalliert ist. Erstellen Sie zunächst ein Demo-Projekt:
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 entleeren . Suchen Sie die Datei
coreclr\src\System.Private.CoreLib\shared\System\Threading\Thread.cs
Und ersetzen Sie
Abort () durch
[SecuritySafeCritical] [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public void Abort() { AbortInternal(); } [System.Security.SecurityCritical]
Jetzt müssen wir die Attribute und die
C ++ - Implementierung zurückgeben. Ich habe es in Teilen aus verschiedenen offenen Repositorys von
.NET Framework gesammelt und der
Einfachheit halber alle Änderungen in Form einer
Pull-Anfrage entworfen .
Hinweis: Beim Erstellen gab es Probleme mit Ressourcen in den "neuen" Attributen, die ich
"Fest" mit Steckern. Denken Sie daran, wenn Sie diesen Code an einem anderen Ort als zu Hause verwenden möchten.Führen
Sie nach der Integration dieser Änderungen in den Code
build.cmd von
coreclr aus . Die Montage in den späteren Phasen kann mit Fehlern übersät sein, aber es ist nicht beängstigend. Die Hauptsache für uns ist, dass
CoreCLR zusammengebaut werden kann. Es wird liegen in:
coreclr\bin\Product\Windows_NT.x64.Debug
Einfacher Weg
Wir führen aus
dotnet publish --runtime win-x64 --self-contained
Dateien von
Windows_NT.x64.Debug werden mit der veröffentlichten Anwendung in den Ordner
verschoben .
Harter Weg
Sobald die Bibliotheken zusammengestellt sind, gehen Sie zu
C:\Program Files\dotnet\shared\Microsoft.NETCore.App
und klonen Sie den Ordner 3.0.0. Wir werden es zum Beispiel 5.0.1 nennen. Wir kopieren dort alles, was in
Windows_NT.x64.Debug liegt, mit Ausnahme der Ordner. Jetzt wird unsere Version von CoreCLR über runtimeconfig verfügbar sein.
Unser Projekt zusammenstellen. Zu
.csproj hinzufügen :
<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>
Wir wiederholen die Manipulationen mit
Nuget aus dem vorherigen Teil des Artikels. Veröffentlichen
dotnet publish --runtime win-x64 --self-contained
Geben Sie in
runtimeconfig.json die folgende Konfiguration ein:
{ "runtimeOptions": { "tfm": "netcoreapp3.0", "framework": { "name": "Microsoft.NETCore.App", "version": "5.0.1" } } }
Ergebnis
Starten Sie!

Die Magie ist passiert. In unseren
.NET Core- Anwendungen wird
Thread.Abort () jetzt wieder ausgeführt. Aber natürlich nur unter
Windows .