如何将System.Data.SQLite合并到一个单一可执行程序中?

5

我正在尝试在C#中创建一个单一可执行文件的应用程序,其中包括SQLite。System.Data.SQLite依赖于一个非托管的DLL(SQLite.Interop.dll),因此我无法将其与ILMerge合并。

我该如何将System.Data.SQLite捆绑到我的项目中,以便我可以生成一个没有附加DLL的单一可执行文件应用程序?


为什么你不为你的应用程序制作一个安装文件呢? - Sergey K
你做不到。正如你所说,它依赖于一个非托管的dll。非托管的dll无法合并到单个可执行文件中。 - Charles Boyung
1
@Serghei,安装程序在系统中散布DLL会使您的代码更难以无错。有了一个可执行文件,如果用户替换它,您就知道他们拥有最新版本。不必担心安装程序是否包含所有正确的DLL以及是否替换了它们。此外,我认为不需要通过向导运行我的微不足道的应用程序可以提供更好的用户体验。 - spiffytech
@Charles 我以前见过用C和C++编写的单个可执行程序,所以我认为即使不是通常的ILMerge方式,也一定有一种方法可以捆绑未管理的库。 - spiffytech
1
有没有一种方法可以将非托管 DLL 打包到 .exe 文件中,在程序运行时将其解压缩到内存中,并从那里引用它,而不是从文件系统引用它? - spiffytech
显示剩余2条评论
1个回答

4
你可以将dll作为嵌入式资源包含在可执行文件中,然后在运行时提取它(这需要程序具有写入dll所在目录的权限)。类似这样的操作:
string sqllitefile = "sqllite.dll";
Assembly currentAssembly = Assembly.GetExecutingAssembly();

using (FileStream fs = fileInfoOutputFile.OpenWrite())
using (Stream resourceStream =currentAssembly.GetManifestResourceStream(sqllitefile))
{
   const int size = 4096;
   byte[] bytes = new byte[4096];
   int numBytes;
   while ((numBytes = resourceStream.Read(bytes, 0, size)) > 0) 
   {
         fs.Write(bytes, 0, numBytes);
   }
   fs.Flush();
   fs.Close();
   resourceStream.Close();
}

还可以从内存流中加载程序集,因此您不必将其写入磁盘。 - bitbonk
2
@bitbonk - 如果需要引用非托管程序集(正如问题所述),那么使用第三方托管程序集该怎么办呢?如果该托管程序集没有设置从内存中读取,它将无法使用它。 - Charles Boyung
是的,你说得对,一旦涉及到非托管 DLL,这种方法就行不通了。 - bitbonk
@Chris B:我该如何添加一个引用到我的项目中,以便System.Data.SQLite知道在哪里找到DLL?我是在编译时硬编码引用并希望能够写入该位置,还是有一种动态添加引用的方法,使得System.Data.SQLite可以看到它? - spiffytech
@spiffytech 你应该使用DllImport,你可以在这里找到更多信息:http://weblogs.asp.net/ralfw/single-assembly-deployment-of-managed-and-unmanaged-code - lithiium

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