从
.NET Framework迁移到
.NET Core时 ,可能会出现一些不愉快的情况。 例如,如果您的应用程序使用域,则必须重写逻辑。
Thread.Abort()的情况与此类似:
微软对此实践非常
不满意 (正确的做法是),他们首先声明
不赞成使用此方法,然后将其完全从框架中删除,而现在却在诡异地抛出
PlatformNotSupportedException 。
但是,如果您的应用程序使用
Thread.Abort() ,并且您
真的想将其转换为
.NET Core而不重写任何内容,该怎么办? 好吧,我们非常清楚该平台甚至支持此功能,所以我可以请您:有一种出路,您只需要组装自己的
CLR版本即可。
免责声明:这是一篇纯实践性的文章,几乎没有理论知识,仅用于演示开发人员与.NET环境之间交互的新选项。 绝对不要在生产中这样做。 但是,如果您真的想...
之所以能够做到这一点,要归功于两件事:
微软对跨平台
.NET Core 的渴望以及开发人员为将框架的源代码转移到开放访问而进行的工作。 让我们利用这一点。
理论最小值:
自定义CoreFX
在继续我们的主要目标(返回
Thread.Abort( ))之前,让我们更改
CoreFX中的一些基本
功能以进行
热身以测试所有工具的功能。 例如,在
上一篇有关
dynamic的 文章中 ,我们完全禁止在应用程序中使用它。 怎么了 因为我们可以。
先决条件
首先,我们将安装组装
所需的
一切 :
- CMake的
- Visual Studio 2019预览版
- 最新的.NET Core SDK(.NET Core 3.0预览版)
Visual Studio 2019-工作负载
.NET桌面开发- 所有必需的组件
- .NET Framework 4.7.2开发工具
使用C ++进行桌面开发- 所有必需的组件
- VC ++ 2019 v142工具集(x86,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工具集(x86,x64)
- VC ++ 2017 v141工具集(x86,x64)
- 编译器
- .NET Framework 4.7.2目标包
- Windows通用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 。 组装完成后,在
Visual Studio中使用以下内容创建一个新的
.NET Core项目:
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
并将
Abort()替换为
[SecuritySafeCritical] [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public void Abort() { AbortInternal(); } [System.Security.SecurityCritical]
现在我们需要返回属性和
c ++实现。 我从
.NET Framework的各种开放存储库中分批收集了这些信息,为方便起见,我以
拉取请求的形式设计了所有更改。
注意:构建时,“新”属性中的资源存在问题,我
带插头“固定”。 如果您想在家庭实验以外的任何地方使用此代码,请记住这一点。将这些更改集成到代码中后,运行
coreclr的 build.cmd 。 后期的组装可能会开始出现错误,但这并不可怕,对我们而言,主要是
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()再次运行。 但是,当然,仅在
Windows上 。