Al migrar de
.NET Framework a
.NET Core , pueden aparecer algunos momentos desagradables. Por ejemplo, si su aplicación usa dominios, tendrá que reescribir la lógica. Una situación similar con
Thread.Abort () : a
Microsoft no le gusta tanto esta práctica (y con razón) que primero declararon este método en
desuso , y luego lo cortaron por completo del marco y ahora arrojan
PlatformNotSupportedException traicioneramente.
Pero, ¿qué
sucede si su aplicación usa
Thread.Abort () y
realmente desea traducirla a
.NET Core sin reescribir nada? Bueno, sabemos muy bien que la plataforma incluso admite esta funcionalidad, así que puedo complacerte: hay una salida, solo necesitas ensamblar tu propia versión del
CLR .
Descargo de responsabilidad: este es un artículo puramente práctico con un mínimo de teoría, diseñado solo para demostrar nuevas opciones de interacción entre el desarrollador y el entorno .NET. Nunca hagas esto en producción. Pero si realmente quieres ...
Esto fue posible gracias a dos cosas:
el deseo
de Microsoft de .NET Core multiplataforma y el trabajo realizado por los desarrolladores para transferir la fuente del marco al acceso abierto. Aprovechemos esto.
Mínimo teórico:
- dotnet publishing nos permite publicar aplicaciones independientes : el marco se entregará con él y no se buscará en algún lugar del GAC
- La versión de CoreCLR en la que se ejecutará la aplicación, bajo ciertas condiciones, se puede configurar usando runtimeconfig.json
- Podemos construir nuestro propio CoreFX : github.com/dotnet/corefx
- Podemos construir nuestro propio CoreCLR : github.com/dotnet/coreclr
Personaliza CoreFX
Antes de pasar a nuestro objetivo principal, devolver
Thread.Abort ( ), cambiemos algo fundamental en
CoreFX para que se
caliente y pruebe la funcionalidad de todas las herramientas. Por ejemplo, siguiendo los pasos de mi
artículo anterior sobre
dinámica , prohibimos por completo su uso en la aplicación. Por qué Porque podemos
Prerrequisitos
En primer lugar, instalaremos
todo lo necesario para el ensamblaje:
- CMake
- Vista previa de Visual Studio 2019
- Último SDK de .NET Core (vista previa de .NET Core 3.0)
Visual Studio 2019 - Cargas de trabajo
Desarrollo de escritorio .NET- Todos los componentes requeridos
- .NET Framework 4.7.2 Herramientas de desarrollo
Desarrollo de escritorio con C ++- Todos los componentes requeridos
- Conjunto de herramientas VC ++ 2019 v142 (x86, x64)
- Windows 8.1 SDK y UCRT SDK
- Conjunto de herramientas VC ++ 2017 v141 (x86, x64)
Desarrollo multiplataforma de .NET Core- Todos los componentes requeridos
Visual Studio 2019: componentes individuales
- Compiladores de C # y Visual Basic Roslyn
- Herramientas de análisis estático
- Paquete de orientación de biblioteca portátil .NET
- Windows 10 SDK o Windows 8.1 SDK
- Características principales de Visual Studio C ++
- Conjunto de herramientas VC ++ 2019 v142 (x86, x64)
- Conjunto de herramientas VC ++ 2017 v141 (x86, x64)
- Msbuild
- .NET Framework 4.7.2 Paquete de orientación
- Windows Universal CRT SDK
Clon corefx :
git clone https://github.com/dotnet/corefx.git
Ahora deshabilitar
dinámico . Abriremos para esto (en adelante indicaré las rutas relativas a la raíz del repositorio)
corefx\src\System.Linq.Expressions\src\System\Runtime\CompilerServices\CallSite.cs
Y al final de la función
CallSite <T>
.Create, inserte el código simple:
throw new PlatformNotSupportedException("No way");
Regresamos a
corefx y ejecutamos
build.cmd . Una vez completado el ensamblaje, cree un nuevo proyecto
.NET Core en
Visual Studio con los siguientes contenidos:
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); }
Compilamos nuestro proyecto. Ahora ve a
corefx\artifacts\packages\Debug\NonShipping
y encontramos un paquete que se parece a esto:
Microsoft.Private.CoreFx.NETCoreApp. 5.0.0-dev.19465.1 .nupkg . Abrimos
.csproj de nuestro proyecto e insertamos allí las siguientes líneas:
<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>
La versión debe ser la misma que en el nombre del paquete ensamblado. En mi caso,
5.0.0-dev.19465.1 .

Vaya a la configuración de
nuget para nuestro proyecto y agregue dos nuevas rutas allí:
corefx\artifacts\packages\Debug\NonShipping corefx\artifacts\packages\Debug\Shipping
Y desmarca todos los demás.

Ve a la carpeta del proyecto y ejecuta
dotnet publish --runtime win-x64 --self-contained
Hecho Solo queda correr:

Funciona! Las bibliotecas no se toman del
GAC , la
dinámica no funciona.
Haga que CoreCLR sea grandioso nuevamente
Ahora pasemos a la segunda parte, devolviendo
Thread.Abort () . Aquí nos espera una sorpresa desagradable: la implementación de
subprocesos reside en
CoreCLR , que no forma parte de
CoreFX y está preinstalado en la máquina por separado. Primero, cree un proyecto de demostración:
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();
Desinflar coreclr . Encuentra el archivo
coreclr\src\System.Private.CoreLib\shared\System\Threading\Thread.cs
Y reemplace
Abort () con
[SecuritySafeCritical] [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public void Abort() { AbortInternal(); } [System.Security.SecurityCritical]
Ahora necesitamos devolver los atributos y la implementación de
c ++ . Lo recogí en partes de varios repositorios abiertos de
.NET Framework y, por conveniencia, diseñé todos los cambios en forma de
solicitud de extracción .
Nota: al construir, hubo problemas con los recursos en los atributos "nuevos", que yo
"Fijo" con enchufes. Tenga esto en cuenta si desea utilizar este código en cualquier lugar que no sea la experimentación en el hogar.Después de integrar estos cambios en el código, ejecute
build.cmd desde
coreclr . El ensamblaje en las etapas posteriores puede comenzar a rociar con errores, pero no da miedo, lo principal para nosotros es que
CoreCLR puede ensamblar. Mentirá en:
coreclr\bin\Product\Windows_NT.x64.Debug
Manera fácil
Llevamos a cabo
dotnet publish --runtime win-x64 --self-contained
Los archivos de
Windows_NT.x64.Debug se colocan en la carpeta con la aplicación publicada.
Camino duro
Una vez que las bibliotecas estén ensambladas, vaya a
C:\Program Files\dotnet\shared\Microsoft.NETCore.App
y clonar la carpeta 3.0.0. Lo llamaremos, por ejemplo, 5.0.1.
Copiamos todo lo que se encuentra en
Windows_NT.x64.Debug , excepto las carpetas. Ahora nuestra versión de
CoreCLR estará disponible a través de runtimeconfig.
Poniendo nuestro proyecto juntos. Añadir a
.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>
<PackageConflictPreferredPackages> Microsoft.Private.CoreFx.NETCoreApp ;. tiempo de ejecución de $ (RuntimeIdentifiers) .Microsoft.Private.CoreFx.NETCoreApp; $ (PackageConflictPreferredPackages) </ PackageConflictPreferredPackages> <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>
Repetimos las manipulaciones con
nuget de la parte anterior del artículo. Publicar
dotnet publish --runtime win-x64 --self-contained
En
runtimeconfig.json, ingrese la siguiente configuración:
{ "runtimeOptions": { "tfm": "netcoreapp3.0", "framework": { "name": "Microsoft.NETCore.App", "version": "5.0.1" } } }
Resultado
Lanzamiento

La magia sucedió. Ahora en nuestras aplicaciones
.NET Core Thread.Abort () se está ejecutando nuevamente. Pero, por supuesto, solo en
Windows .