2019-10-4-C#-极限压缩-dotnet-core-控制台发布文件
title | author | date | CreateTime | categories |
---|---|---|---|---|
C# 极限压缩 dotnet core 控制台发布文件
|
lindexi
|
2019-10-04 14:59:36 +0800
|
2019-10-04 14:51:48 +0800
|
dotnet C#
|
每次发布 dotnet core 应用都会觉得发布文件太大,而如果使用极限压缩,用 CoreRT 能让发布的控制台文件到 5KB 左右,不需要带框架就能在其他设备运行
这是微软 MichalStrehovsky 大佬,也就是 CoreRT 项目开发者给的方法
在开始写代码之前,需要定义一些基础的类,因为不包含任何运行环境,所以基础的 object 这些都需要重新定义,这里的代码放在 github 我也在本文最后贴出代码
现在输出控制台的代码不是原先的 Console.WriteLine 而是通过底层方法
unsafe class Program
{
[DllImport("api-ms-win-core-processenvironment-l1-1-0")]
static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("api-ms-win-core-console-l1-1-0")]
static extern IntPtr WriteConsoleW(IntPtr hConsole, void* lpBuffer, int charsToWrite, out int charsWritten, void* reserved); static int Main()
{
string hello = "Hello world!";
fixed (char* c = hello)
{
int charsWritten;
WriteConsoleW(GetStdHandle(-11), c, hello.Length, out charsWritten, null);
} return 42;
}
}
最难的是如何编译这个文件
编译需要先使用 csc 编译为 IL 代码,然后通过 ilcompiler 编译为obj文件,然后通过 link 编译为运行文件
从开始菜单找到 x64 Native Tools Command Prompt for VS 2019 然后进入上面代码所在文件夹,执行下面代码编译
csc /debug:embedded /noconfig /nostdlib /runtimemetadataversion:v4.0.30319 zerosharp.cs /out:zerosharp.ilexe /langversion:latest /unsafe
编译完成可以看到 zerosharp.ilexe 文件,然后通过 ilcompiler 将这个文件编译为 zerosharp.map 和 zerosharp.obj 文件
在自己的 NuGet 缓存文件里面找到 runtime.win-x64.microsoft.dotnet.ilcompiler 库,可以在资源管理器地址输入下面代码找到缓存文件
%appdata%..\..\..\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler
找到里面的最新版本,在文件夹里面的 tools 文件夹可以找到 ilc.exe 文件,如在我电脑的的文件是
c:\Users\lindexi\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\1.0.0-alpha-27606-05\tools\ilc.exe
记下这个路径,接下来将使用这个工具编译
>c:\Users\lindexi\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\1.0.0-alpha-27606-05\tools\ilc.exe zerosharp.ilexe -o zerosharp.obj --systemmodule zerosharp --map zerosharp.map -O
然后用 link 连接
link /subsystem:console zerosharp.obj /entry:__managed__Main kernel32.lib /merge:.modules=.pdata /incremental:no
执行上面代码就可以编译 zerosharp.exe 文件,这个文件只有5KB可以将这个程序放在其他设备运行
下面是所有代码
using System;
using System.Runtime.InteropServices; #region A couple very basic things
namespace System
{
public class Object { IntPtr m_pEEType; }
public struct Void { }
public struct Boolean { }
public struct Char { }
public struct SByte { }
public struct Byte { }
public struct Int16 { }
public struct UInt16 { }
public struct Int32 { }
public struct UInt32 { }
public struct Int64 { }
public struct UInt64 { }
public struct IntPtr { }
public struct UIntPtr { }
public struct Single { }
public struct Double { }
public abstract class ValueType { }
public abstract class Enum : ValueType { }
public struct Nullable<T> where T : struct { } public sealed class String { public readonly int Length; }
public abstract class Array { }
public abstract class Delegate { }
public abstract class MulticastDelegate : Delegate { } public struct RuntimeTypeHandle { }
public struct RuntimeMethodHandle { }
public struct RuntimeFieldHandle { } public class Attribute { } namespace Runtime.CompilerServices
{
public class RuntimeHelpers
{
public static unsafe int OffsetToStringData => sizeof(IntPtr) + sizeof(int);
}
}
}
namespace System.Runtime.InteropServices
{
public sealed class DllImportAttribute : Attribute
{
public DllImportAttribute(string dllName) { }
}
}
#endregion #region Things needed by ILC
namespace System
{
namespace Runtime
{
internal sealed class RuntimeExportAttribute : Attribute
{
public RuntimeExportAttribute(string entry) { }
}
} class Array<T> : Array { }
} namespace Internal.Runtime.CompilerHelpers
{
using System.Runtime; class StartupCodeHelpers
{
[RuntimeExport("RhpReversePInvoke2")]
static void RhpReversePInvoke2() { }
[RuntimeExport("RhpReversePInvokeReturn2")]
static void RhpReversePInvokeReturn2() { }
[System.Runtime.RuntimeExport("__fail_fast")]
static void FailFast() { while (true) ; }
[System.Runtime.RuntimeExport("RhpPInvoke")]
static void RphPinvoke() { }
[System.Runtime.RuntimeExport("RhpPInvokeReturn")]
static void RphPinvokeReturn() { }
}
}
#endregion unsafe class Program
{
[DllImport("api-ms-win-core-processenvironment-l1-1-0")]
static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("api-ms-win-core-console-l1-1-0")]
static extern IntPtr WriteConsoleW(IntPtr hConsole, void* lpBuffer, int charsToWrite, out int charsWritten, void* reserved); static int Main()
{
string hello = "Hello world!";
fixed (char* c = hello)
{
int charsWritten;
WriteConsoleW(GetStdHandle(-11), c, hello.Length, out charsWritten, null);
} return 42;
}
}
2019-10-4-C#-极限压缩-dotnet-core-控制台发布文件的更多相关文章
- 【ASP.NET Core分布式项目实战】(五)Docker制作dotnet core控制台程序镜像
Docker制作dotnet core控制台程序镜像 基于dotnet SDK 新建控制台程序 mkdir /home/console cd /home/console dotnet new cons ...
- 如何将dotnet core webapi发布到docker中…
如何将dotnet core webapi发布到docker中 今天想起来撸一下docker,中途还是遇到些问题,但是这些问题都是由于路径什么的导致不正确,在这儿还是记录下操作过程,今天是基于wind ...
- Supervisor守护DotNet Core控制台程序
Supervisor 相信对Linux系统很熟的都知道这个软件,基于Python写的一个守护进程软件.具体的介绍和使用我就不再赘述了. 使用asp.net core 部署在Linux常用的方法 我们可 ...
- CYQ.Data 正式支持 DotNET Core 版本发布
闲话几句: 自从上周开始,IOS人员逝去,就开始接手IOS的代码了. 并开始整理IOS的代码(包括当时一开始设计的开发框架). 在未来不远的日子里,设想是有一个系列详细的介绍I恋App和IT连App及 ...
- 2017-03-04 dotnet core网站发布到Linux系统中
今天开始学习dotnet core的开发,距离Visual Stuio 2017正式版的发布,也就是VS20周岁的生日还有三天,在我的电脑上安装的是VS2017 Enterprise RC版, 在VS ...
- Docker制作dotnet core控制台程序镜像
(1)首先我们到某个目录下,然后在此目录下打开visual studio code. 2.编辑docker file文件如下: 3.使用dotnet new console创建控制台程序; 4.使用d ...
- [尝鲜]妈妈再也不用担心 dotnet core 程序发布了: .NET Core Global Tools
什么是 .NET Core Global Tools? Global Tools是.NET Core 2.1 中一个初次出现的特性.Global Tools提供了一种方法,让开发人员编写的.NET C ...
- dotnet core webapi 发布部署到docker的步骤
1. 创建web api项目,编译并测试成功 2. 在项目的根目录添加Dockerfile文件,注意:Dockerfile文件名区分大小写 文件内容如下 # 基于microsoft/dotnet:la ...
- dotnet Core 2.0学习笔记(一)
一:Dotnet Core Windows运行环境,标红部分要注意 https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites ...
随机推荐
- 25 面向对象设计实例——基于PCL点云库的通用工具开发
0 引言 问题背景:pcl中提供了大量工具,用于对点云和三角面片文件进行处理和显示.在研究中,存在很多简易的需求,比如点云坐标转换,点云的打开显示以及同步显示,点云的最小包络求解,点云的格式转换等等. ...
- ST表 (模板) 洛谷3865
题目背景 这是一道ST表经典题——静态区间最大值 请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1) O(1) 题目描述 给定一个长度为 N N 的数列,和 M M ...
- luoguP3951 小凯的疑惑/P2662 牛场围栏
其实就是当年sxy给我讲的墨墨的等式,只是当时比较菜听得似懂非懂. 小凯的疑惑 去年noipday1t1,当时随便猜了个结论结果猜对了,现在瞎证一下,答案是a*b-a-b. 设a为a,b中较小的一个, ...
- NX二次开发-UFUN工程图表格注释section转tag函数UF_TABNOT_ask_tabular_note_of_section
NX9+VS2012 #include <uf.h> #include <uf_tabnot.h> #include <NXOpen/Part.hxx> #incl ...
- centos7.5下coredns+etcd搭建DNS服务器
coredns简介 安装etcd 安装coredns 设置域名解析 A记录 AAAA记录 CNAME记录 SRV记录 TXT记录 coredns简介 CoreDNS是一个DNS服务器,和Caddy S ...
- sql中desc的妙用
很多情况下对表内部结构不熟悉,想看下我创建的表里面又多少表明,又想他按照首字母的规律排列, 这时候就要用desc +表名了. desc t_bike_info; hive> desc t_bik ...
- 基于Netty的RPC架构学习笔记(八):protocol buff学习使用
文章目录 简介 准备 protobuf配置文件 生成java代码 举个
- 过滤'and','or' ''' '*' '=' ‘select’下的注入
遇到一个站:http://www.马赛克.net/intro.aspx?id=6 加了单引号 http://www.马赛克.net/intro.aspx?id=6‘ 页面无变化 加了双引号 h ...
- [21]APUE:线程同步之记录锁(文件)
[a] 概念 建议锁:在遵循相同记录锁规则的进程/线程间生效,通常用于保证某个程序自身多个进程/线程间的数据一致性 强制锁:意在保证所有进程间的数据一致性,但不一定有效:如不能应对先 unlink 后 ...
- sp_executeSql 用法 执行有参数的sql字符串 出现必须声明标量变量 "@XXX"。
今天遇到了一个难题 就是把 一个拼接sql语句 的返回值 赋值给一个变量 经研究 要用sp_executeSql这个存储过程 据说是从sql 2005才开始有的 代码如下: declare @str ...