我有一个Windows C#程序,它使用C++ DLL进行数据i/o.我的目标是将应用程序部署为单个EXE.
创建这样的可执行文件有哪些步骤?
2007年2月4日星期日,托管和非托管代码的单一部署
.NET开发人员喜欢XCOPY部署.他们喜欢单组装组件.至少我总觉得有点不安,如果我必须使用一些组件并且需要记住一个文件列表,也包括该组件的主程序集.因此,当我最近不得不开发一个托管代码组件并且不得不使用来自C DLL的一些非托管代码来扩充它时(thx到Marcus Heege帮我解决这个问题!),我想到了如何更容易部署这两个DLL .如果这只是两个程序集,我可以使用ILmerge将它们打包在一个文件中.但这对于具有托管和非托管DLL的混合代码组件不起作用.
所以这就是我提出的解决方案:
我将我想要部署的任何DLL包含在我的组件的主程序集中作为嵌入式资源.然后我设置一个类构造函数来提取这些DLL,如下所示.我认为,类ctor在每个AppDomain中只调用一次,因此这是一个可忽略的开销.
namespace MyLib { public class MyClass { static MyClass() { ResourceExtractor.ExtractResourceToFile("MyLib.ManagedService.dll", "managedservice.dll"); ResourceExtractor.ExtractResourceToFile("MyLib.UnmanagedService.dll", "unmanagedservice.dll"); } ...
在这个例子中,我包括两个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); } } }
像这样使用托管代码程序集与通常一样 - 差不多.您在组件的主项目(此处为:MyLib)中引用它(此处为:ManagedService.dll),但将Copy Local属性设置为false.此外,您将程序集中的链接作为现有项链接,并将构建操作设置为嵌入式资源.
对于非托管代码(此处为:UnmanagedService.dll),您只需将DLL作为现有项链接,并将Build Action设置为Embedded Resource.要访问其功能,请像往常一样使用DllImport属性,例如
[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);
而已!只要使用静态ctor创建类的第一个实例,嵌入式DLL就会被提取到自己的文件中,并且可以像使用它们作为单独的文件一样使用.只要您具有执行目录的写权限,这应该适合您.至少对于原型代码,我认为这种单组件部署方式非常方便.
请享用!
http://weblogs.asp.net/ralfw/archive/2007/02/04/single-assembly-deployment-of-managed-and-unmanaged-code.aspx