怎么可能一个C++windows dll被合并成一个C#应用程序exe?
题
我有一个窗C#程序,使用C++dll数据i/o.我的目标是部署应用程序作为一个单一的EXE。
什么步骤来创建这样一个可执行的?
解决方案
单一的组装部署的管理和管理的代码 星期天,二月4日,2007年
.网开发的爱XCOPY部署。他们喜欢单一的组装部件。至少我总是感觉有点不安,如果我必须用某些部件和需要记住的文件列表也包括与主要组件的组成部分。所以当我最近不得不发展一个管理编码的分量,不得不增加它与一些非托管的代码C DLL(谢谢马库斯Heege对我的帮助与此!), 我以为关于如何使它更容易部署的两个Dll。如果这只是两个组件,我可以使用ILmerge收拾他们在只是一个文件。但是,这不起作用的混合代码组成的管理及非管理Dll。
所以这是我想出了一个解决方案:
I包括任何Dll我要部署我的组件主要大会作为嵌入的资源。然后我设立了一个类的构造中提取这些Dll如下。类的构造函数是所谓的只是一次在各个程序域使其neglible开销的,我想。
namespace MyLib
{
public class MyClass
{
static MyClass()
{
ResourceExtractor.ExtractResourceToFile("MyLib.ManagedService.dll", "managedservice.dll");
ResourceExtractor.ExtractResourceToFile("MyLib.UnmanagedService.dll", "unmanagedservice.dll");
}
...
在这个例子包括我的两个Dll资源,其中之一是一个非管理的编码问题,和一个在被托管的代码DLL(只是为了示范的目的),以显示,如何这种技术适用于这两种类型的代码。
代码以提取Dll到文件中的自己是简单的:
public static class ResourceExtractor
{
public static void ExtractResourceToFile(string resourceName, string filename)
{
if (!System.IO.File.Exists(filename))
using (System.IO.Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
{
byte[] b = new byte[s.Length];
s.Read(b, 0, b.Length);
fs.Write(b, 0, b.Length);
}
}
}
工作与管理的码会一样,这是和往常一样-几乎。你参考(这里:ManagedService.dll)在组件的主要项目(此处:MyLib),但设定的复制本地财产假。另外,你的链接,在大会作为一个现有项目和组的建立作为嵌入的资源。
对管理的代码(:UnmanagedService.dll)你只是链接在DLL作为一个现有项目和组的建立作为嵌入的资源。访问其功能的使用DllImport属性如往常一样,例如
[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);
这就是它!只要你创建的第一个实例类的静态构造函数的嵌入式Dll获得提取到的文件他们自己的和准备利用为如果部署了它们作为单独的文件。只要你有写入权限执行目录,这应适用于你。至少对于典型的代码我认为这种方式的单一的组装的部署是比较方便的。
享受!
其他提示
尝试 boxedapp;它允许负载的所有Dll从存储器。此外,看来你甚至可以嵌入。净运行时间。良好的创造一个真正独立的应用程序...
使用 福迪鸟.Costura nuget
- 打开你的解决方案->项目>管理Nuget包
- 搜索 福迪鸟.Costura
- 汇编 你的 项目.
这就是它!
资料来源: http://www.manuelmeyer.net/2016/01/net-power-tip-10-merging-assemblies/
你有没有尝试过ILMerge? http://research.microsoft.com/~mbarnett/ILMerge.aspx
ILMerge是一个实用工具,可以用于合并多个。网组成一个单一的组装。它是免费提供使用的工具和实用工具页Microsoft。净框架的开发中心。
如果你在建筑C++DLL的 /clr
标识(全部或部分C++/CLI),那么它应的工作:
ilmerge /out:Composite.exe MyMainApp.exe Utility.dll
它不会与一个普通的(地)Windows DLL但是。
只是右击中的项目Visual Studio,选择的项目属性-->资源-->增加的资源-->增加现有的文件... 和包括代码下面的应用。停靠。cs或等效的。
public App()
{
AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
dllName = dllName.Replace(".", "_");
if (dllName.EndsWith("_resources")) return null;
System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
byte[] bytes = (byte[])rm.GetObject(dllName);
return System.Reflection.Assembly.Load(bytes);
}
这是我的原始博客的员额:http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/
Thinstall 是一个解决方案。对于一个本地的windows的应用程序,我建议将DLL作为二进制的资源的对象,那么提取它在运行时之前,你需要它。
智能型组件 可以这样做,并更多。如果你dll管理的代码,它不会让你合并dll到一个单一的组件,而不是它可以嵌入所需的相关性作为资源的主exe。其触面,它不是免费的。
你可以做这种手工嵌入dll您的资源,然后依靠域议会 ResolveHandler
.当涉及到混合模式dll,我发现许多变体和口味的 ResolveHandler
方法不会为我工作(所有其读dll字节的内存和读取)。他们所有的工作对于管理dll。这里是什么工作对我来说:
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
string assemblyName = new AssemblyName(args.Name).Name;
if (assemblyName.EndsWith(".resources"))
return null;
string dllName = assemblyName + ".dll";
string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);
using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
{
byte[] data = new byte[stream.Length];
s.Read(data, 0, data.Length);
//or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);
File.WriteAllBytes(dllFullPath, data);
}
return Assembly.LoadFrom(dllFullPath);
};
}
这里的关键是要写的字节的文件和载荷从其位置。为了避免鸡和蛋的问题,你必须要确保宣布的处理程序以前访问会和你不要访问的会员(或者任何东西的实例,具有处理大会)内部装(大会解决)的一部分。也照顾到确保 GetMyApplicationSpecificPath()
不是任何临时目录由于临时文件可能是企图得到清除通过其他程序或通过自己(而不是它将被删除,而你的节目访问的启动,但至少其有害。应用程序数据是良好的位置)。还注意到,你必须写字节每一次,你不能负荷来自位置仅仅是因为dll已经驻留在那里。
生成后从 Xenocode 可以打包了两个管理和unmanged入一个单一的exe。