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 ...
随机推荐
- bzoj1022题解
[题意分析] 最简单的Anti-Nim博弈模型. [解题思路] 引理:SJ定理 对于一个Anti-Nim游戏,只要有以下两条条件之一,先手必胜: 1.游戏的总SG函数为0且任意子游戏的SG函数不超过1 ...
- luoguP3281 [SCOI2013]数数
传送门 抄的llj的代码 还有点问题没弄懂,先码着 //Achen #include<algorithm> #include<iostream> #include<cst ...
- HDU4578-代码一点都不长的线段树
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 题意:传送门 原题目描述在最下面. 4种操作,1:区间加法,2:区间乘法,3:区间的所有数都变成一个数,4:访问区间每个数的p次方 ...
- CodeForces 1166C A Tale of Two Lands
题目链接:http://codeforces.com/problemset/problem/1166/C 题目大意 给定 n 个数,任选其中两个数 x,y,使得区间 [min(|x - y|, |x ...
- Linux环境下Jmeter 报错:Unable to get local host IP address
主要是没有在host中配置本机ip hostname查看本机名 [root@test task]# hostname test [root@test task]# 打开 [root@test task ...
- 6-MySQL高级-索引
索引 1. 思考 在图书馆中是如何找到一本书的? 一般的应用系统对比数据库的读写比例在10:1左右(即有10次查询操作时有1次写的操作), 而且插入操作和更新操作很少出现性能问题, 遇到最多.最容易出 ...
- 【POJ】2253 Frogger
= =.请用C++提交.. 如果有朋友能告诉我G++和C++交题什么机制..我感激不尽.G++杀我. 题目链接:http://poj.org/problem?id=2253 题意:青蛙A要去找B约会, ...
- D3.js的基础部分之数组的处理 集合(Set)(v3版本)
数组的处理 之 集合(set) 集合(Set)是数学中常用的概念,表示具有某种特定性质的事物的总体.集合里的项叫做元素.集合的相关方法有: d3.set([array]) //使用数组来构建集合, ...
- pandas中axis的含义
定义一个dataframe: >>> df a b0 1 31 2 4 现在看两种用法: 1.求行的均值 >>> df.mean(axis=1)0 2.01 3.0 ...
- iOS音频开发系列-概述篇
概述 iOS中对于音频的处理,苹果提供了两个库. AVFoundation AudioToolbox 在iOS系统中apple对上述的流程进行了封装并提供了不同层次的接口