NuGet:两个包含目标文件的包导致错误复制DLL

NuGet:两个包含目标文件的包导致错误复制DLL,nuget,target,Nuget,Target,我创建了两个包含本机库的NuGet包。第一个包含两个子文件夹(amd64和x86),第二个包含构建目录下的DLL平面。第一个包的NativeLibrary应该复制到OutputPath的子文件夹中。第二个包中的唯一DLL应平铺复制到OutputPath下。我使用以下stackoverflow条目作为创建包的指南: firstNuGet软件包文件夹结构如下所示(生成中的amd64和x86子文件夹): 建造 amd64 DLL1.dll DLL2.dll x86 DLL1.dll DLL

我创建了两个包含本机库的NuGet包。第一个包含两个子文件夹(amd64和x86),第二个包含构建目录下的DLL平面。第一个包的NativeLibrary应该复制到OutputPath的子文件夹中。第二个包中的唯一DLL应平铺复制到OutputPath下。我使用以下stackoverflow条目作为创建包的指南:

firstNuGet软件包文件夹结构如下所示(生成中的amd64和x86子文件夹):

  • 建造
    • amd64
      • DLL1.dll
      • DLL2.dll
    • x86
      • DLL1.dll
      • DLL2.dll
    • packagename.targets
第一个目标文件:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs1 Include="$(MSBuildThisFileDirectory)*.dll" />
    <None Include="@(NativeLibs1)">
      <Link>%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

因此,NativeLib显然是在第三次或第四次重建之后从另一个NuGet包中添加的。

我认为您正在对非sdk net framework项目使用
Packages.config
NuGet包格式。如果是的话,这是可以解释的

对于
packages.config
nuget管理格式,它直接在csproj文件下导入目标文件。在我这边,我创建了两个名为Flat1.0.0和Faltt1.0.0的nuget包

您可以查看我的csproj文件:

如果是这样,则第一个导入目标文件
flat.targets
文件与第一个nuget包的目标文件相同:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs1 Include="$(MSBuildThisFileDirectory)*.dll" />
    <None Include="@(NativeLibs1)">
      <Link>%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
它将
x86
amd64
文件夹文件包括到
output folder\x86
output folder\amd64
文件夹中,这是我们所期望的

但是
packages.config
下,由于两个目标文件位于同一个csproj文件中,因此当msbuild在
flat.targets
文件之后读取
falt.targets
文件时,它们可以相互访问(它们在同一个
csproj
中具有相同的生命周期),另外,您没有更改第二个目标文件的
NativeLibs
项,它本身具有以下文件:

C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\amd64\Dll1.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\amd64\Dll2.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\x86\Dll1.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\x86\Dll1.dll
读取
flatt.targets
文件时,它还包括
C:\Users\xxx\source\repos\flat\packages\flatt.1.0.0\build\x86\Dll1.dll

So它在
NativeLibs
项下有五个文件

然后执行
%(文件名)%(扩展名)
,第一个nuget包的DLL将在第二个nuget包的节点下执行,并输出到输出根文件夹

由于
Packages.config
导入目标文件的特殊性质,它们是交错的

你应该注意到 在PackageReferencenuget管理格式下,导入目标文件存储在
obj\xxx.csproj.nuget.g.targets
文件下,如下所示:

 <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
    <Import Project="$(NuGetPackageRoot)flatt\1.0.0\build\flatt.targets" Condition="Exists('$(NuGetPackageRoot)flatt\1.0.0\build\flatt.targets')" />
    <Import Project="$(NuGetPackageRoot)flat\1.0.0\build\flat.targets" Condition="Exists('$(NuGetPackageRoot)flat\1.0.0\build\flat.targets')" />
  </ImportGroup>

重新打包项目时,首先卸载它们,删除
C:\Users\xxx\.nuget\packages
下的所有缓存文件。然后重新安装包。

我认为您使用的是带有packages.config numget包管理格式的非sdk net framework项目,对吗?在我这边,将PackageReference用于新的sdk项目以获得正确的行为。事实上,两个目标文件不应该互相访问,因为它们是两个不同的单一nuget软件包。我使用的是一个非sdk net framework项目,但带有PackageReference。感谢您的回复,我现在对过程有了一点了解。但是,对于具有PackageReference的非sdk.NET Framework项目,也存在这个问题。然而,对我来说,只有在第三次或第四次重建之后(我不知道为什么)。你能重现这种行为吗?我已经在我的初始问题中添加了一些信息,这使得重现和调查更加容易。两个目标
OutputPackage1NativeLibs
OutputPackage2NativeLibs
无法显示此问题下的内容,因为它们都取决于构建。当它在构建过程之前执行时,
NativeLibs
已经包含了这五个文件,因为NativeLibs项一直在增加,但不是空的(项应该在所有目标之前读取)。因为它们都取决于构造,所以它们总是相同的。所以你所做的不能作为判断标准。因此,它们无法使用某些目标显示文件。我的意思是,msbuild项读取
NativeLibs
,然后在所有目标之前执行的
obj\xxx.csproj.nuget.g.targets
期间复制到输出文件夹是分开的。当您使用一些目标来获取这些项目时,它已经完成了所有复制步骤,并显示了两个包中的所有文件,然后覆盖这些文件。在我身边。它显示得很好,复制的文件不会在多次重建中相互混淆。不确定您的
obj\xxx.csproj.nuget.g.targets
是否仍然是错误的上一个文件,并且重建(清除+构建)不会删除它。它已由还原处理。因此,我们的判断基于最终输出文件夹中的文件是否正确。请删除
bin
obj
文件夹。然后,再次重建以检查该问题。更好的是,您应该在两个nuget目标文件中将
NativeLibs
项更改为两个不同的名称,在这种情况下不会出现任何问题。