将.NET应用程序转换为x86本地代码

23

这是一个完全使用C#编写,面向.NET Framework 2.0的程序。 有没有办法将托管的可执行文件编译为本地代码,使其不依赖于.NET?我知道可能有商业产品可以实现这个目的……但它们有点昂贵。

问题在于,我们需要在运行没有安装.NET Framework的Windows XP计算机上部署该程序。还有一个要求是,程序的大小不能超过500Kb(最大1Mb),因为它是从Web服务器下载的(目前大小为255Kb)。因此,我们无法将完整的.NET FX(甚至是精简版)附加到下载的程序文件中。

很明显,这是一种可怕的软件工程错误,早期应该被发现和避免,以使用像C++之类的本地技术。

目前我们尝试使用Novell的Mono——一个适用于Linux、MAC和Windows的.NET Framework的开源实现。Mono由C#编译器、集成开发环境、运行时(CLR)和类库(如System.dll和mscorlib.dll——非常类似于.NET的类库,在GAC中安装)组成。 我们尝试做的是找到CLR文件,并将其与我们的程序文件和一些程序集一起打包。这样,用户可以通过在计算机上运行“mono program.exe”(命令提示符)来调用程序。 除了这种使用方式的不便外,CLR文件(mono.exe和mono.dll)总共约为2.5 Mb,远大于所需的500Kb甚至1 Mb。

因此,我们别无选择,只能通过编译器将我们的.NET应用程序转换为本地应用程序,但问题仍然存在——我们应该使用哪个编译器,以及在哪里可以找到它……

目前我偶然发现了微软研究部门的Singularity OS项目,它是一个开源研究操作系统,至少部分是用托管代码编写的。Singularity OS包括Bartok编译器,该操作系统使用它将托管程序转换为本机程序(x86 32位)。需要注意的是,Bartok无法将.NET 2.0的所有方面都转换为本机代码,但可以转换大部分内容。但是我还没有学会如何使用Singularity...

如果您能就这个问题向我提供一些有用的提示和建议,分享一下您对Singularity OS和Bartok编译器或其他解决此问题的方法的经验,我将不胜感激。

非常感谢!

最后,在Callum Rogers的建议下,利用Mono的Full AOT功能,我成功生成了一个program.exe.dll文件,但它缺少CLI标头。因此,它看起来像一个本机dll。但是我无法弄清楚如何将该dll转换为exe或使其运作。此外,该dll似乎没有公开任何重要函数,如主函数。


3
请勿上当受骗:https://dev59.com/GXVD5IYBdhLWcg3wOpBh - Alastair Pitts
你是想让它跨平台,还是只是去除框架库的依赖关系? - Rowland Shaw
我只是试图消除.NET Framework的依赖性,以便在未安装.NET FX的Windows XP上运行它。 - Vlad
3
另一个重复问题:如何将.NET可执行文件转换为本地可执行文件。 - Mauricio Scheffer
1
这是一个非常值得思考的好问题,我甚至可以补充说Windows 7已经预装了.NET 3.5 SP1。不幸的是,有时候在目标计算机上发现遗留操作系统,可能只安装了旧版本(最好的情况)或者根本没有安装(最坏的情况).NET。 - Vlad
5个回答

10

了解一下来自Mono项目的AOT(Ahead Of Time)编译。这将把您的托管项目编译成本地exe或elf可执行文件(取决于您所针对的系统),无需JIT即可运行。这是将mono应用程序放入iPhone上的技术(在那里不允许使用JIT/Framework),还具有更快的启动时间,更低的内存使用和使代码更难反编译的附加优势。您说您已经在使用Mono,所以它应该兼容。

mono-project.com网站和Miguel de Icaza's 博客(以及iPhone信息)中了解更多相关信息。

请注意,您不能使用动态代码或泛型接口。

interface IFoo<T> {
...
    void SomeMethod ();
}

你需要编译所有使用的库的DLL。

PS:确保为问题使用“Full”AOT。


谢谢您的回答。看来我之前尝试过以这种方式编译一个样例Hello World汇编程序,但失败了。可能是因为[Mono的Full AOT]与每个处理器不兼容(我有Intel Core 2 Duo)。然而,我会仔细研究Full AOT,因为很有可能是我做错了什么。 - Vlad
完整的AOT至少适用于x86和x86-64,以及ARM和PPC处理器。 - Gonzalo
终于,我成功生成了一个缺少CLI头的program.exe.dll。所以它看起来像一个本地dll。然而,我无法弄清楚如何将该dll转换为exe或使其可操作。而且这个dll似乎没有暴露出任何感兴趣的函数,比如主函数。 - Vlad
1
即使使用完整AOT编译,Mono的已使用部分也将被编译为.exe文件,使其远远超过500k或1 Mb的大小限制。因此,实际上这将在没有.NET的情况下运行,但它不会满足所给出的大小限制。我担心唯一的方法是重新编写代码或强制在目标计算机上安装.NET Framework。 - Sebastian P.R. Gingter
有人在Windows上成功进行了完全AOT吗?它在x86 Linux上可以工作,但似乎不支持Windows x86。 - Camilo Martin

9

2018年更新

在Build 2018上,微软宣布了.Net Core 3.0路线图,支持Windows桌面应用程序(Winform和WPF)。

2017年更新

对于控制台应用程序,您可以使用.net core的Self-contained deployments (SCD)。即使是一个hello world应用程序,您的包也会有50MB +。但仍需要安装VC运行库。

更新

根据@jenix的评论,.NET Native仅适用于Windows Store应用程序(UWP)。在它宣布三年后,这仍然是真实的,微软可能会放弃桌面版的.net native。因此,本答案不再适用。

========

微软在Build 2014上宣布了.NET Native Preview

使用.NET Native Developer Preview,应用程序将作为完全自包含的本地编译代码部署在最终用户设备上,并且不依赖目标设备/机器上的.NET Framework。因此,使用.NET Native不需要在目标计算机上安装.NET框架。

宣布.NET Native Preview
Microsoft .NET Native


@JenixGuy 是的,两年后。 - prime23

3

有一个名为CrossNet的项目,它可以解析.Net程序集并生成非托管C++代码,可以在任何标准编译器中进行编译。


它解析程序集还是代码?抱歉问这个问题,但这个项目对我来说有点困惑。 - Camilo Martin

1

谢谢。我会关注列表中提到的程序。然而,据我所知,这些程序并不便宜,但可能存在重要的负载,即我们可执行文件的大小将超过预期的数字。 - Vlad
链接似乎已经失效。 - Brian Reichle

0

除了费力地重写应用程序之外,我并不确定还有什么其他的办法。为了简化已经繁琐的过程,您可以使用像Reflector这样的工具(将.NET应用程序反汇编为Microsoft C++),并以此作为基础开始,只需将托管C++引用替换为本机引用。


1
我希望能找到一种避免重写整个应用程序为C++的方法,因为这将需要相当多的时间,最重要的是调试时间。 - Vlad

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