你能否编译C#,使其在运行时不需要.NET Framework?

32

是否有可能强制C#编译器将所有引用的调用从框架中提取出来并打包成dll甚至单个可执行文件?

我喜欢使用C#编写快速的“一次性”应用程序,但是我不想在目标计算机上安装整个框架。


1
看看Delphi吧。它完全符合你的要求。.Net的历史可以追溯到Delphi,所以你应该会觉得很亲切。你真的不需要.Net,它只是不必要的开销。 - William Egge
一个更好的解决方案是将您的应用程序容器化。例如使用Docker。 - ldgorman
8个回答

38

你问的问题有点含糊。C# 仅仅是一种编程语言,不需要 .NET Framework。编译它的过程需要编译器,该编译器可能或可能不会依赖于 .NET Framework(Microsoft 的 C# 编译器并不依赖 -- 它是用本地代码编写的)。你的程序需要引用一些程序集,以便使用其中的类型、类和方法。你可以从引用列表中删除 system.dll 和 mscorlib.dll 并引用自己的程序集。因此,如果你真的努力工作,可以避免对 .NET Framework 的依赖。但最终,除非你有一个将程序编译为本地代码的 C# 编译器,否则你仍然依赖于 CLR。

这段话在技术上表述得很抽象,几乎没有讲到什么。但它回答了你的问题。 :) 更实际有用的是如何让你的 C# 程序运行时依赖尽可能少的程序。mono 中的 mkbundle 实际上可以让你将所有内容编译成一个几乎不依赖其他程序的 .exe 文件。

但如果你想继续使用微软的 .NET Framework,你可以通过使用 .NET 3.5 SP1 的客户端配置文件来实现更轻量级、更快速安装常用依赖项的效果。你可以在这里阅读更多信息: http://msdn.microsoft.com/en-us/library/cc656912.aspx


我正在尝试使用Visual Studio做同样的事情,但被告知这是不可能的。 - muttley91
“这个相同的东西”是什么?我在这里谈论了几个选项。 - Andrew Arnott
这是我最喜欢的答案部分...“但是,最终,除非您有一个将程序编译为本机代码的C#编译器,否则您仍然依赖于CLR。”虽然这是可能的,但并不明智,因为我认为人们不想编写自己的编译器:);我也不是mono的铁杆粉丝,但这只是因为维护模拟器非常困难,而且在最好的情况下也很容易出错(在我看来)。 - Mike Perrenoud
有关客户端配置文件停用的MSDN页面 - Roman

14

我确信很久以前有一个Windows工具可以做到这一点。也许是ILMerge? - configurator
有没有适用于Mono IDE的Windows安装程序?我已经找到了源代码,但是很难找到二进制文件。我本来可以编译它,但这会给我更多的机会搞砸一些东西... - Brian Sweeney
一个安装程序可在http://www.go-mono.com/mono-downloads/download.html 下载(点击Windows图标,链接将出现)。 - denis phillips
那个链接似乎没有包括IDE,只有其他工具和库,除非我弄错了。不幸的是,似乎你仍然需要从cygwin内部下载IDE源代码并编译和运行。 - Brian Sweeney

10

使用Microsoft .NET Native现在可以将C#编译为本地代码:

https://msdn.microsoft.com/zh-cn/library/dn584397(v=vs.110).aspx

它自动将使用托管代码(C#或Visual Basic)编写且针对.NET Framework和Windows 10的应用程序的发布版本编译为本机代码。

...

对于您的应用程序用户,.NET Native提供以下优势:

•快速执行时间

•始终如一的快速启动时间

•低部署和更新成本

•优化的应用程序内存使用

这仅适用于Visual Studio .NET 2015。


5

5

对于一个如此丑陋的网站来说,它看起来像一个了不起的产品,特别是当您担心源代码被盗时,因为混淆对于真正的黑客来说几乎是微不足道的。 - Chris Marisic

1

不可能的。你的“编译”后的C#应用程序是一种语言,.Net CLR在运行时解释(应该说是JITed,读取IL,编译为本机代码,然后调用已编译的本机代码)。

顺便说一下,.net 2.0是xp SP2和vista的标准安装,所以你不会付出太大的代价。

你可以研究一下mono,但这仍然涉及在目标机器上运行某种框架。


3
「你的“编译”后的C#应用程序是一种在运行时由.Net CLR解释的语言。」- 这是错误的,不正确的。当某个托管代码在特定计算机上第一次运行时,它会被即时(JIT)编译成该计算机的本地代码。C#从未被解释。 - tomfanning
1
@tomfanning 但是您仍然需要CLR来运行编译的代码,对吧?因此,如果第一次运行字节码时进行JIT编译,即使在后续运行中也由CLR管理,那么将CLR描述为“在运行时解释(代码)”有什么问题呢? - Kyle Strand
@tomfanning 我想这很公平!我的意思是,这种情况与Java有显著的不同吗?在Java中,字节码是由JVM运行的。我发现这个问题是因为我看到了一篇博客文章,其中列举了具有不同抽象级别的语言的示例,并将C#放在比Java更低的级别,这让我感到惊讶,因为我认为C#在概念上几乎与Java相同。 - Kyle Strand
@TomFanning C# 的不安全代码和 P/Invoke 功能使您能够直接将内嵌的 C++/C/汇编代码嵌入到执行代码中。在 Java 中,您可以使用 JNI 实现相同的功能,但是在 C# 中,您可以在本地级别上进行指针交互,而无需使用其他语言来实现它。 - Spence
@Spence,我真的不确定为什么这个问题在5年后又被提起,但据我所知,unsafe关键字和平台调用功能(extern关键字)并不会将C++、C或汇编嵌入到C#中。虽然unsafe允许直接指针操作,但extern只允许您调用非托管库中的方法。我甚至认为它们并没有特别相关,而且与问题也没有什么关系。 - tomfanning
显示剩余3条评论

0

这种依赖关系在现实世界中经常会出现问题或者缺失,这是 C# 没有更广泛应用的一个重要原因。另一方面,大多数开发确实都有依赖关系...例如 C++ 和 Java。

我认为我们不可能很快摆脱这些依赖关系问题,所以如果你想使用 C#,我建议你制作一个安装包包装器,检查你需要的 .net framework 版本依赖关系,如果缺失则通知用户他们需要此项才能运行你的应用程序。


-2
一些C#功能与.NET框架的接口绑定。
例如: yield return需要IEnumerable接口 using (x) {}需要IDisposable接口

1
这与楼主所问的无关。他询问的是将 .NET 库与程序一起进行静态编译。 - Camilo Martin
原标题是“你能在不使用 .Net 框架的情况下编译 C# 吗?” - Rauhotz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接