MSBuild错误MSB3021:无法复制文件。找不到文件'obj\Release\myWebProject1.dll'。

31
使用TeamCity编译我的MSBuild XML任务脚本时,出现以下错误:
[10:43:03]: myWebProject1\ myWebProject 1 .csproj (3s)
[10:43:07]: [ myWebProject1\ myWebProject1 .csproj] _CopyWebApplicationLegacy
[10:43:07]: [_CopyWebApplicationLegacy] Copy
[10:43:07]: [Copy] C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets(131, 5): error MSB3021: Unable to copy file "obj\Release\myWebProject1.dll" to "C:\MSBUILDRELEASE\myWebProject1\\bin\myWebProject1.dll". Could not find file 'obj\Release\myWebProject1.dll'.

当我在本地运行时,它是正常工作的。
当我将本地输出与构建服务器输出进行比较时,构建服务器上缺少一些文件。例如,global.asax文件在构建服务器的输出目录中缺失(但在本地编译时没有问题)。这是为什么呢?
以下是我的当前MSBuild脚本:
<?xml version="1.0" encoding="utf-8"?>
<Project
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  ToolsVersion="4.0"
  DefaultTargets="Build">

  <PropertyGroup>
    <OutputDir>C:\MSBUILDRELEASE</OutputDir>
  </PropertyGroup>

  <ItemGroup>
    <ProjectToBuild Include="UtilityApp.sln" >
      <Properties>OutputPath=$(OutputDir);Configuration=MSBuildRelease;Platform=x86</Properties>
    </ProjectToBuild>
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Projects="@(ProjectToBuild)"/>
            <CallTarget Targets="Publish WebProject1" />
            <CallTarget Targets="Publish WebProject2" />  
  </Target>

<Target Name="Publish WebProject1">
 <RemoveDir Directories="$(OutputFolder)"
       ContinueOnError="true" />
 <MSBuild Projects="WebProject1\WebProject1.csproj"
      Targets="ResolveReferences;_CopyWebApplication"
      Properties="WebProjectOutputDir=$(OutputDir)\WebProject1\;
      OutDir=$(OutputDir)\WebProject1\;Configuration=Release;Platform=AnyCPU" />
</Target>

<Target Name="Publish WebProject2">
 <RemoveDir Directories="$(OutputFolder)"
       ContinueOnError="true" />
 <MSBuild Projects="WebProject2\WebProject2.csproj"
      Targets="ResolveReferences;_CopyWebApplication"
      Properties="WebProjectOutputDir=$(OutputDir)\WebProject2\;
      OutDir=$(OutputDir)\WebProject2\;Configuration=Release;Platform=AnyCPU" />
</Target>

</Project>

我可以在本地运行这个脚本,而且似乎工作正常(没有生成错误)。但是当我在构建服务器上运行它时,会出现MSBuild错误MSB3021。
现在,当我将本地构建输出文件与服务器构建输出文件进行比较时,服务器输出文件没有那么多。例如,全局.ASAX文件在我的构建服务器的输出中缺失。为什么它在本地对我有效,但在我的TeamCity构建服务器上无效?有什么区别,我该如何修复?
我注意到TeamCity构建代理错误消息有一个奇怪的目录路径: "C:\MSBUILDRELEASE\myWebProject1\bin\myWebProject1.dll"
^ 在bin文件夹之前有两个斜杠。我没有在任何地方指定这个。是什么原因?我有一种感觉我没有正确构建我的Web项目(也许需要使用不同的任务方法?)。它在本地似乎工作正常,但在我的构建服务器上却不行。
我是否正确构建我的Web项目?这些只是用于Web服务(ASMX)部署的简单Web项目。帮帮我?

我遇到了类似的问题。看起来这是由于dll编译位置的问题引起的。使用Configuration=Release时,文件输出到obj\Release\,如果Configuration=Debug,则输出到obj\Debug\。但是如果你有Configuration=SomethingElse,我的文件会输出到obj\SomethingElse,但MSBuild仍然会查找obj\Release。我的配置“SomethingElse”是从Release配置复制过来的……为什么它不会查找正确的文件夹呢?我认为这是VS2010中_CopyWebApplicationLegacy目标的问题。 - Carl
我建议你删除开发机器上obj文件夹中的所有文件和文件夹,然后再次尝试运行msbuild脚本。我想象一下,如果你的问题像我的一样,你在本地机器上得到的错误与你在构建服务器上得到的错误是相同的。 - Carl
我遇到的另一种情况是相关文件被标记为只读。在我的情况下,一个来自源代码控制的杂项 DLL 被标记为只读。当我从 DLL 中移除只读属性时,问题得以解决。如果文件被标记为只读,MSBuild 将不会将文件复制到它们自己上面。 - John Dyer
15个回答

12

好的,我弄清楚了。这是一个“配置”不匹配的问题。你有一个项目使用Configuration=MSBuildRelease构建,另外两个项目使用Configuration=Release构建。然后MSBuild会在错误的位置查找“中间”程序集。

将你的代码更改为以下内容:

<?xml version="1.0" encoding="utf-8"?>
<Project
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  ToolsVersion="4.0"
  DefaultTargets="Build">

  <PropertyGroup>
    <OutputDir>C:\MSBUILDRELEASE</OutputDir>
  </PropertyGroup>

  <ItemGroup>
    <ProjectToBuild Include="UtilityApp.sln" >
      <Properties>OutputPath=$(OutputDir);Configuration=MSBuildRelease;Platform=x86</Properties>
    </ProjectToBuild>
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Projects="@(ProjectToBuild)"/>
            <CallTarget Targets="Publish WebProject1" />
            <CallTarget Targets="Publish WebProject2" />  
  </Target>

<Target Name="Publish WebProject1">
 <RemoveDir Directories="$(OutputFolder)"
       ContinueOnError="true" />
 <MSBuild Projects="WebProject1\WebProject1.csproj"
      Targets="ResolveReferences;_CopyWebApplication"
      Properties="WebProjectOutputDir=$(OutputDir)\WebProject1\;
      OutDir=$(OutputDir)\WebProject1\;Configuration=MSBuildRelease;Platform=AnyCPU" />
</Target>

<Target Name="Publish WebProject2">
 <RemoveDir Directories="$(OutputFolder)"
       ContinueOnError="true" />
 <MSBuild Projects="WebProject2\WebProject2.csproj"
      Targets="ResolveReferences;_CopyWebApplication"
      Properties="WebProjectOutputDir=$(OutputDir)\WebProject2\;
      OutDir=$(OutputDir)\WebProject2\;Configuration=MSBuildRelease;Platform=AnyCPU" />
</Target>

</Project>

我实际上还没有能够测试这个。最后我使用CruiseControl.NET来构建我的.NET解决方案,它工作得更容易。TeamCity的支持非常缓慢,并且一直将责任归咎于Microsoft。而Microsoft的支持则会把责任推给他们。因此,CruiseControl.NET已经运行起来,在几个小时内就构建了我的应用程序。也许最终我会迁移到TeamCity,因为我正在使用TeamCity构建我的FLEX和FLASH项目。谁知道呢,但我将您的答案标记为正确的解决方案。 - D3vtr0n
我有时会看到类似的 MSBuild 错误,尽管对我来说,它始终是关于从 <full path>\bin\Debug\MyProject.dll 复制到 bin\Debug\MyProject.dll,在某些日子里突然开始失败了。它确实与配置有关,将受影响的项目切换到 Release 而不是 Debug(否则为解决方案中的所有项目设置)将防止问题发生。还不确定如何令人满意地解决这个问题,但感谢您提供关于配置的提示。 - O. R. Mapper
谢谢。通过将我的发布输出更改为指向调试输出的位置,解决了我的问题。当我尝试使用发布版本构建时,出现了这个错误,而调试一直在工作。 - Shane van Wyk
这个回答至少让我看了一下TC使用的配置。谢谢。 - Hulvej

6

我经常在长时间未打开的旧项目中遇到这个问题。

对我有用的解决方案是:

  1. 打开项目文件夹并删除bin文件夹enter image description here

  2. 确保项目配置设置为Debug而不是Releaseenter image description here

  3. 构建项目 - VS将创建新的bin文件夹

    enter image description here

我认为这个问题与发布方式有某种关系。


4
花了3个小时解决这个bug后,我开始了一个新项目,并逐个导入旧项目中的每个文件。在每个文件之间编译都是成功的,直到我添加了最后一个文件。
我以为问题与最后一个文件有关,但通过移除其他文件,我意识到只有在我的项目中包含特定数量的文件时才会出现此问题。
我不能确定原因,但我通过添加/删除具有随机名称的空类来解决了这个问题。
经过几次添加/编译/删除/再次编译,VS开始正常工作。

2
我有一个想法,我注意到您正在使用Platform=x86构建解决方案,然后使用Platform=AnyCPU调用这两个Web项目。如果这两个项目是由解决方案构建的,则构建和部署后的输出位置可能不同。
其他一些注意事项:
我通常避免使用CallTarget,并且在您的情况下更喜欢以下形式:
<Target Name="BuildProjects">
    <MSBuild Projects="@(ProjectToBuild)" />
</Target>
<Target Name="Build"
    DependsOnTargets="BuildProjects;Publish WebProject1;Publish WebProject2"
    />

通常双斜杠表示以下两种情况之一:
$(OutDir)\$(Intervening)\bin

如果$(Intervening)为空,则未评估中间属性,或者路径的某个部分已经以尾随斜杠结束,如果$(OutDir)属性已经有一个尾随斜杠。

我从来不知道目标名称中可以有空格,我不得不检查一下以确保它能够工作!


双反斜杠问题我已经解决了,应该像这样:"Properties="WebProjectOutputDir=$(OutputDir)\WebProject1;" 不要有尾部斜杠。OutDir属性需要一个尾部斜杠。你觉得呢? - D3vtr0n
我突然意识到错误信息中没有指定完整路径。它试图使用“obj\Release\myWebProject1.dll”。我该如何更改以使用完整路径?我只指定了两个路径(WebProjectOutputDir和OutDir)。我不知道哪里出了问题? - D3vtr0n
一般情况下,$(OutDir)的值为"bin\Debug",但您似乎在两个发布目标的MSBuild任务调用中传递了项目文件夹。您是否可能混淆了标准的$(OutDir)属性和自定义的$(OutputDir)属性? - Brian Kretzler
今天我在我的构建服务器上安装了Visual Studio 2010(专业版)。我通过VS命令提示符运行了构建脚本。但是我收到了相同的错误“无法复制文件”等等。这很奇怪,因为当我在开发机器上构建时一切正常,没有错误。只有在我的构建服务器上才会出现这种情况。有什么想法吗?_CopyWebApplication相关的.target文件呢? - D3vtr0n
现在奇怪的是,我可以通过命令行在我的构建服务器上编译它。但是当我使用TeamCity运行它时,它会产生这个错误。它应该是完全相同的脚本和编译器。我不知道为什么会这样。微软一直让我联系TeamCity支持。我们拭目以待。 - D3vtr0n
1
将诊断记录器“/fl /flp:v=diag;logfile=log.txt”附加到两个构建的命令行中,即可用于工作的命令行构建和失败的TeamCity构建,然后对比这两个日志文件。请注意每个项目的部分,其中列出了属性和项值。理想情况下,它们应该是相同的,因此任何重大差异可能会提供线索。 - Brian Kretzler

1

删除“obj”和“bin”文件夹后,我的项目再次构建。


1

当我通过实体框架连接MDF时,遇到了同样的问题。通过简单地清理解决方案并重建它来解决它。希望能有所帮助。


1

如果你的构建被MSB3021破坏了,首先检查你的防病毒软件设置。我的防病毒软件有一个名为实时文件系统保护的功能。每当创建或修改文件时,它会将其抓取进行分析,导致文件被锁定。当我禁用此功能后,MSB3021消失了。


谢谢!我必须进入Avast设置,通过右键单击任务栏中的图标>隔离...>选择我的文件旁边的...>还原并添加例外。 - Seth Schaffner

0
我在尝试部署到AppHarbor时遇到了这个问题,对我来说,将文件排除再重新包含它解决了这个问题。

0

我的解决方法是打开任务管理器(对于Windows)或监视器(对于Mac),然后杀死所有的Visual Studio和相关进程。


0

我遇到了同样的错误。看一下目标框架。因为我的失误,我把netcore从2.1改成了2.0。


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