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-控制台发布文件的更多相关文章

  1. 【ASP.NET Core分布式项目实战】(五)Docker制作dotnet core控制台程序镜像

    Docker制作dotnet core控制台程序镜像 基于dotnet SDK 新建控制台程序 mkdir /home/console cd /home/console dotnet new cons ...

  2. 如何将dotnet core webapi发布到docker中…

    如何将dotnet core webapi发布到docker中 今天想起来撸一下docker,中途还是遇到些问题,但是这些问题都是由于路径什么的导致不正确,在这儿还是记录下操作过程,今天是基于wind ...

  3. Supervisor守护DotNet Core控制台程序

    Supervisor 相信对Linux系统很熟的都知道这个软件,基于Python写的一个守护进程软件.具体的介绍和使用我就不再赘述了. 使用asp.net core 部署在Linux常用的方法 我们可 ...

  4. CYQ.Data 正式支持 DotNET Core 版本发布

    闲话几句: 自从上周开始,IOS人员逝去,就开始接手IOS的代码了. 并开始整理IOS的代码(包括当时一开始设计的开发框架). 在未来不远的日子里,设想是有一个系列详细的介绍I恋App和IT连App及 ...

  5. 2017-03-04 dotnet core网站发布到Linux系统中

    今天开始学习dotnet core的开发,距离Visual Stuio 2017正式版的发布,也就是VS20周岁的生日还有三天,在我的电脑上安装的是VS2017 Enterprise RC版, 在VS ...

  6. Docker制作dotnet core控制台程序镜像

    (1)首先我们到某个目录下,然后在此目录下打开visual studio code. 2.编辑docker file文件如下: 3.使用dotnet new console创建控制台程序; 4.使用d ...

  7. [尝鲜]妈妈再也不用担心 dotnet core 程序发布了: .NET Core Global Tools

    什么是 .NET Core Global Tools? Global Tools是.NET Core 2.1 中一个初次出现的特性.Global Tools提供了一种方法,让开发人员编写的.NET C ...

  8. dotnet core webapi 发布部署到docker的步骤

    1. 创建web api项目,编译并测试成功 2. 在项目的根目录添加Dockerfile文件,注意:Dockerfile文件名区分大小写 文件内容如下 # 基于microsoft/dotnet:la ...

  9. dotnet Core 2.0学习笔记(一)

    一:Dotnet Core Windows运行环境,标红部分要注意 https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites ...

随机推荐

  1. LUOGU P4560 [IOI2014]Wall 砖墙 (线段树)

    传送门 解题思路 线段树打标记,刚开始想复杂了,维护了四个标记.后来才知道只需要维护一个最大值最小值即可,然后更新的时候分类讨论一下. 代码 #include<iostream> #inc ...

  2. 牛客网 NOIP赛前集训营-普及组(第四场)C--部分和 (高维前缀和)

    传送门 解题思路 高维前缀和模板题.首先,求前缀和有两种方式,比如说对于求二维前缀和来说. 第一种 : for(int i=1;i<=n;i++) for(int j=1;j<=n;j++ ...

  3. NX二次开发-UF_MODL_ask_distance_tolerance获取建模的长度公差

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_ui.h> UF_initialize() ...

  4. NX二次开发-NX11创建表达式组NXOpen::ExpressionGroup

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_part.h> #include < ...

  5. JVM内核-原理、诊断与优化学习笔记(三):常用JVM配置参数

    文章目录 Trace跟踪参数 -verbose:gc (打开gc的跟踪情况) -XX:+printGC(打开gc的log开关,如果在运行的过程中出现了gc,就会打印出相关的信息.) -XX:+Prin ...

  6. PAT_A1064#Complete Binary Search Tree

    Source: PAT A1064 Complete Binary Search Tree (30 分) Description: A Binary Search Tree (BST) is recu ...

  7. [17]APUE:线程

    通常情况下,线程模型的并发性能优于进程模型,但不总是这样 线程的优势: 线程的创建.销毁及上下文切换代价比进程低 某些情况下,使用线程可以简化逻辑,避免异步编程的复杂性 同一进程内所有线程共享全局内存 ...

  8. grep 的一些常用用法

    打印匹配到的上下5行 grep -C 5 'root' /etc/passwd            上下5行 grep -A 5 'root' /etc/passwd            afte ...

  9. 2018今日头条湖北省赛【H】

    [题目链接]https://www.nowcoder.com/acm/contest/104/G 现场赛的H题,emmm...C++选手表示很伤心.高精度压四位板子WA四发. 题意很简单就是给你n个数 ...

  10. QT5+Pylon

    VS+QT+Pylon:配置一下包含文件和libs,具体参考pylon说明文档. Windows下  Qtcreator+Pylon:建议把include和libs文件夹拷贝至工作目录,然后修改.pr ...