当引用的项目需要SQLite.Interop.dll文件时,该文件未复制到项目输出路径。

24
我使用System.Data.SQLite Core版本:1.0.98.1 nuget包与Visual Studio 2015。当我构建引用系统数据SQLite包的项目时,它会将两个文件夹(x86和x64),每个文件夹都包含一个SQLite.Interop.dll复制到输出目录中。然而,当我构建我的测试项目或任何其他引用上述项目的项目时,这些文件夹不会被复制到父项目的输出目录中,并且我会在SQLite.Interop.dll上收到DllNotFoundException。
注意:这特别是当引用System.Data.SQLite的项目被另一个项目引用时。
2个回答

49

根据此处记录的推荐解决方案是在您的packages\System.Data.SQLite.Core.1.0.98.1\build\[您的框架版本]文件夹中创建一个名为System.Data.SQLite.Core.targets.user的文件,其中包含以下内容:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup> 
        <ContentSQLiteInteropFiles>true</ContentSQLiteInteropFiles>
        <CopySQLiteInteropFiles>false</CopySQLiteInteropFiles>
        <CleanSQLiteInteropFiles>false</CleanSQLiteInteropFiles>
        <CollectSQLiteInteropFiles>false</CollectSQLiteInteropFiles>
    </PropertyGroup>
</Project>

但是,如果您不想在软件包文件夹中添加任何内容到您的源代码控制中,您可以直接将以下内容添加到您的项目文件中

<PropertyGroup> 
    <ContentSQLiteInteropFiles>true</ContentSQLiteInteropFiles>
    <CopySQLiteInteropFiles>false</CopySQLiteInteropFiles>
    <CleanSQLiteInteropFiles>false</CleanSQLiteInteropFiles>
    <CollectSQLiteInteropFiles>false</CollectSQLiteInteropFiles>
</PropertyGroup>

SDK风格项目更新

在新的SDK项目风格中,解决嵌套项目和包之间依赖项的方式发生了变化。在构建过程中,会解析资源并生成一个obj\project.assets.json文件,列出来自各种依赖项的资源。然后使用项目资产文件确定要导入哪些目标以及需要将哪些文件复制到输出目录中。 然而,从非直接依赖项中包含资产的方式有所不同。build文件夹中的目标文件不会从非直接依赖项中导入。旧的解决方法依赖于将System.Data.SQLite.Core.targets导入到父项目中。直接依赖于System.Data.Sqlite的项目可以通过在PackageImport中添加PrivateAssets="none"来覆盖此行为。您还需要将其添加到依赖链中的每个PackageImport或ProjectReference中。但是,您无需将其与先前的解决方法组合使用。

概述:

对于直接引用System.Data.Sqlite的项目,将PrivateAssets="none"添加到您的PackageImport中。

<PackageReference Include="System.Data.SQLite.Core" Version="1.0.112" PrivateAssets="none"/>

对于您依赖链中的每个项目,直到您的根项目,也要添加PrivateAssets="none"

<ProjectReference Include="..\MyProject.csproj" PrivateAssets="none"/>

2
我的本地构建一切正常——CopySQLiteInteropFiles 运行良好,并将文件复制到我的机器的 OutDir 中。但是在 TeamCity 上进行测试时,相同的构建失败了——缺少 Interop 文件导致 Dll 未找到异常。 在我的 proj 文件中创建 CopySQLiteInteropFiles 属性是让 TeamCity 成功复制 interop 文件的方法。+1 - Kurt Johnson
3
第二个解决方案对我非常有效。如果你从NuGet获得了新版本,推荐的方法不是立即升级吗? - quarkonium
我有一个WinForm项目,引用了一个带有SQLite的SDK项目。我尝试在SDK和WinForm中都使用PrivateAssets="none",但是WinForm项目在bin或发布文件列表中都没有interop dll。 (vs2019)有什么想法吗? - CephalidOne
好的,所以对于我来说,只需将 PrivateAssets="none" 添加到链中的每个依赖项即可解决问题!这也可以在 VS UI 中作为 NuGet 引用的属性使用。请注意,在链中的最后一个非 SDK 样式项目中,我什么都没有做,它也起作用了。 - Nicolas

3
<ContentSQLiteInteropFiles>true</ContentSQLiteInteropFiles> 在使用 .NET Standard 2.0 时似乎没有效果,因为在引用项目中 SQLite.interop.dll 仍然不被识别为内容或依赖项。希望有人能找到更清晰的解决方案...
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard20</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Data.SQLite.Core" Version="1.0.112" GeneratePathProperty="true" />
  </ItemGroup>

  <ItemGroup>
    <!-- Fix to get SQLite.interop.dll copied when using netstandard -->
    <Content Include="$(PkgSystem_Data_SQLite_Core)\runtimes\win-x86\native\netstandard2.0\SQLite.Interop.dll" Link="x86\SQLite.Interop.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="$(PkgSystem_Data_SQLite_Core)\runtimes\win-x64\native\netstandard2.0\SQLite.Interop.dll" Link="x64\SQLite.Interop.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

</Project>

@BenCamps 谢谢,看起来更简洁了 - 但正如你所说的那样,这将需要所有其他项目也设置一个包属性,而我的当前解决方法并没有这样做。 - Michel Jansson
1
然而,新的SDK样式项目格式不再使用位于您项目目录中的packages文件夹。新的packages文件夹位于%userprofile%/.nuget/packages。但更清晰的解决方案是使用GeneratePathsProperty在您的项目文件中创建一个变量来引用包目录,无论它在哪里。 - BenCamps
@BenCamps 啊,谢谢提醒!我想我的旧包文件夹还完好无损,因为我刚刚升级了。我已经相应地更新了我的答案。 - Michel Jansson
这个很好用,但是在创建我的项目的NuGet包时出现了错误。 NuGet.Build.Tasks.Pack.targets(221, 5): [NU5118] 文件未添加,因为包已经包含文件“content\SQLite.Interop.dll”。 NuGet.Build.Tasks.Pack.targets(221, 5): [NU5100] 程序集“content\SQLite.Interop.dll”不在“lib”文件夹中,因此在将包安装到项目中时不会将其添加为引用。如果需要引用,请将其移动到“lib”文件夹中。还有其他人遇到过这个问题吗? - dberry

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