NuGet中的System.Data.SQLite,interop dll未复制到输出目录

28
我安装了System.Data.SQLite Core (x86/x64) from NuGet。它没有警告地构建,但是抛出了关于SQLite.Interop.dllSystem.DllNotFoundException异常。我将我的项目设置为从NuGet包目录下复制SQLite.Interop.dll到输出目录,现在它可以正常运行了。
为什么NuGet包没有配置我的项目将适当的interop dll放入输出目录?看起来它应该能够做到这一点。
我对interop很陌生,并且我继承了这个代码库,之前通过路径直接引用了System.Data.SQLite.dll。我切换到NuGet以消除有关项目处理器架构与System.Data.SQLite不匹配的警告。我正在尝试将所有项目都构建为AnyCPU。
10个回答

25

3
成功了!我花了6.5个小时才找到这个。 - Joshua Lumley

9
在我的情况下,问题出在我在一个类库项目中使用SQLite,而这个类库项目又被另一个WPF(图形用户界面类型)项目所使用。
通过在项目属性 -> 构建事件 中使用以下后期构建命令解决了 SQL.Interop.dll 无法复制到输出目录的问题:
xcopy "$(SolutionDir)packages\System.Data.SQLite.Core.1.0.101.0\build\net451\x86\SQLite.Interop.dll" "$(OutputDir)" /y /f

/y overwrites
/f displays actual filenames being copied

5
使用版本为1.0.104的System.Data.SQLite.Core NuGet包时,我遇到了与@Eternal21和@Patrick相同的问题。也就是说,项目A引用SQLite,而项目B引用A,其中SQlite.Interop.dll未复制到B的输出目录中。
我找到了一个解决方案,可以解决项目A中的麻烦,而不是B,这是一种更健壮的解决方案,因为它可以为所有将来引用A的项目修复问题。NuGet包的.targets文件包含以下部分:
<ItemGroup Condition="'$(ContentSQLiteInteropFiles)' != '' And
                      '$(ContentSQLiteInteropFiles)' != 'false' And
                      '@(SQLiteInteropFiles)' != ''">
  <Content Include="@(SQLiteInteropFiles)">
    <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>

这一部分将SQLite.Interop.dll添加为引用,需要将其复制到项目A的输出目录以及其他引用它的项目(如B)的输出目录中。但是默认情况下,MSBuild属性ContentSQLiteInteropFiles未定义(我不知道为什么),这会使第一个条件下的引用失效。要启用它,我在项目A的.csproj文件的PropertyGroup元素中添加了以下行:

<ContentSQLiteInteropFiles>true</ContentSQLiteInteropFiles>

请注意,此行必须在 NuGet 包的 .targets 文件的 Import 元素之前。

1
谢谢!这解决了我的问题。 - Artyom Shalkhakov

5
我曾经遇到过相似的问题,当我将输出文件从我的输出文件夹复制到另一个位置时进行部署。我错过了这样一个事实,即interop文件确实被复制了,但它们是在您的输出文件夹中的x64和x86文件夹中复制的。
如果您在项目上运行msbuild调试,可以查找对CopySQLiteInteropFiles目标的引用,以确保它正在运行。

1
有趣,我确实在那里看到它们。所以,它将它们复制到运行时找不到的位置?我想知道它是否应该适用于特定机器构建。我尝试了x86和x64构建,但出现了错误。可能是我的问题,不确定。 - Vimes
它们在运行时被找到。如果我删除那些文件夹,就会出现加载错误。如果我不这样做,就能正常工作。我之所以发现这一点,是因为我正在将文件从输出目录复制到另一个位置以运行,而我没有复制子目录。 - Richard
4
不是为我。运行时我会收到一个 DllNotFoundException 错误。你所有的项目都是以 AnyCPU 构建的吗? - Vimes
2
在我的情况下,我不得不在起始项目上添加NuGet包引用。我们开发的插件之一使用Sqlite,但仅在该库上添加NuGet包并没有起作用。我不得不在主项目上添加它。 - user1892410
这可能与单元测试项目有关吗?也许,在常规项目中,Interop-DLL 被正确复制了,但在单元测试项目中没有被复制? - realbart

4

在我的情况下,SQL.Interop.dll没有以任何方式由Nuget复制,手动将正确版本的dll放入x86和x64文件夹中解决了问题。

如果您已从Nuget安装Sqlite,则可以在此文件夹中找到SQL.Interop.dll(适用于.NET 4.0)

PROJECT_FOLDER\packages\System.Data.SQLite.Core.1.0.*.*\build\net40


同样的问题。Nuget没有将SQLite.Interop.dll添加到输出文件夹中。我不得不使用后期构建事件自己放置它。 - Eternal21

2

在我的情况下,myProject.csproj文件中没有定义System.Data.SQLite.Core.targets。我添加了以下行,并且现在为所有构建目标复制x64x86版本的SQLite.Interop.dll

<Import Project="..\packages\System.Data.SQLite.Core.1.0.98.1\build\net45\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.98.1\build\net45\System.Data.SQLite.Core.targets')" />

我不确定当System.Data.SQLite.Core的NuGet包更新时会发生什么,是否需要手动更改包路径。


1
在我的情况下,我使用NuGet来安装SQLite,但仍然需要手动添加SQliteinterop.dll作为资源。然后我构建了我的项目,当我发布它时,它可以正常工作。(使用x86配置)

1
我添加了。
<PropertyGroup>
        <ContentSQLiteInteropFiles>false</ContentSQLiteInteropFiles>
        <CopySQLiteInteropFiles>false</CopySQLiteInteropFiles>
        <CleanSQLiteInteropFiles>false</CleanSQLiteInteropFiles>
        <CollectSQLiteInteropFiles>false</CollectSQLiteInteropFiles>
</PropertyGroup>

在引用NuGet包的项目的csproj文件中,这部分需要放在'System.Data.SQLite.Core.targets'的'Import'之上。
然后,在csproj文件中添加以下内容,以便将x64版本的'SQLite.Interop.dll'放置在bin文件夹中。
    <ItemGroup>
        <Content Include="..\packages\System.Data.SQLite.Core.1.0.111.0\build\net46\x64\SQLite.Interop.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
    </ItemGroup>

尽管此语句需要在NuGet包更新时进行更改。

0

我有一个使用NuGet中SQLite包的DLL项目,但是为其编写的测试项目总是会引发DLL未找到异常。

我找到的最简单的解决方案是将SQLite NuGet包也添加到测试项目中。


0

以上的答案似乎都对我无效,可能是因为我使用的是VS2015,但这让我想到了一个好的解决方法来解决这个问题。

我的具体情况与@Eternal21相同——我有一个WPF UI,它使用一个客户端库,该库通过nuget添加了SQLite。是的,问题在于Interop.dll没有被复制到启动应用程序(即没有安装SQLite的WPF UI)中。

如果你很着急,那么简单地使用nuget将SQLite添加到WPF项目中就是一个快速而简单的解决方法。

我的解决方案略微繁琐,使用XCOPY命令,但它有一个优点,即可以复制x86和x64目录,并且还可以处理Debug和Release版本。它的缺点是包含硬编码的项目名称。我可以看出你可以使用宏来摆脱第一个,但我不容易看出如何摆脱第二个,所以如果项目名称更改,你必须手动更改它(但这种情况相当少见)。

我的解决方案是在启动项目的后期构建中使用这些XCOPY命令:

xcopy $(SolutionDir)DALProject\bin\$(ConfigurationName)\x64\SQLite.Interop.dll $(SolutionDir)WPFProject\bin\$(ConfigurationName)\x64\*.* /C /F /S /E /Y
xcopy $(SolutionDir)DALProject\bin\$(ConfigurationName)\x86\SQLite.Interop.dll $(SolutionDir)WPFProject\bin\$(ConfigurationName)\x86\*.* /C /F /S /E /Y

/C - 即使出现错误也继续复制(也许这不是必需的)。

/F - 显示正在复制的文件的完整路径(可以省略以清理生成输出)。

/S - 复制子目录(这是我能够创建 /x86 和 /x64 文件夹的唯一方法)。

/E - 复制目录和子目录(可能重复 /S)。

/Y - 如果目标文件已经存在,则禁止提示。

我将其设置为仅在成功构建时运行,对我非常有效。希望能帮到某些人。


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