如何防止devenv在后台静默调用Compile目标?

时间:2014-11-26 06:06:49

标签: c# visual-studio visual-studio-2012 msbuild devenv

我注意到当我在命令行上运行devenv时,它会在继续前台编译之前进行后台编译。我强烈怀疑我的环境出现了严重问题。

请观察:

PS C:\work\a> dir


    Directory: C:\work\a


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        11/26/2014  12:40 AM            .hg
-a---        11/25/2014  11:48 PM         87 .hgignore
-a---        11/26/2014  12:39 AM        264 1.ps1
-a---        11/26/2014  12:38 AM       1594 a.csproj
-a---        11/26/2014  12:43 AM          2 in.txt


PS C:\work\a>

其中

1.ps1

param([switch]$msbuild)

$in="in.txt"
(dir $in).LastWriteTime = Get-Date
dir $in |% { $_.Name + " : " + $_.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.ffffff") }
if ($msbuild)
{
  msbuild .\a.csproj /v:m
}
else
{
  devenv .\a.csproj /build Debug /SafeMode
}

这是一个简单的Powershell脚本:

  1. 触摸输入文件
  2. 打印时间戳
  3. 使用msbuild或命令行devenv构建项目。
  4. a.csproj

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
      <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
        <ProjectGuid>{EB5EB1C9-DC39-4E48-875B-094CBC0F468A}</ProjectGuid>
        <ProjectTypeGuids>{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
        <OutputType>Library</OutputType>
        <AppDesignerFolder>Properties</AppDesignerFolder>
        <RootNamespace>a</RootNamespace>
        <AssemblyName>a</AssemblyName>
        <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
        <FileAlignment>512</FileAlignment>
        <TargetFrameworkProfile />
        <OldToolsVersion>2.0</OldToolsVersion>
        <OutputPath>bin\$(Configuration)</OutputPath>
      </PropertyGroup>
      <ItemGroup>
        <None Include="in.txt" />
      </ItemGroup>
      <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
      <PropertyGroup>
        <CompileDependsOn>$(CompileDependsOn);MyTarget</CompileDependsOn>
      </PropertyGroup>
      <Target Name="A" BeforeTargets="_CheckForInvalidConfigurationAndPlatform" Condition="Exists('out.txt')">
        <ItemGroup>
          <Out Include="out.txt"/>
        </ItemGroup>
        <Message Text="%(Out.Identity) : %(Out.ModifiedTime)" Importance="High" />
      </Target>
      <Target Name="MyTarget" Inputs="in.txt" Outputs="out.txt">
        <Message Text="Touching now ..." Importance="High" />
        <Touch Files="out.txt" AlwaysCreate="true" />
      </Target>
    </Project>
    

    正如您所看到的,这是一个简单的C#项目,根本没有任何源代码。它:

    • MyTarget目标注入CompileDependsOn列表。
    • 在运行任何与构建相关的目标之前输出输入文件的时间戳(in.txt)。
    • 如果输入文件比输出文件(out.txt)新,则运行MyTarget并打印消息并触摸输出文件

    现在,当我运行要求devenv命令行构建的脚本时会发生什么:

    PS C:\work\a> .\1.ps1
    in.txt : 2014-11-26 00:44:09.078676
    
    Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0.
    Copyright (C) Microsoft Corp. All rights reserved.
    1>------ Build started: Project: a, Configuration: Debug Any CPU ------
    1>  out.txt : 2014-11-26 00:44:09.7744589
    1>  a -> C:\work\a\bin\Debug\a.dll
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
    PS C:\work\a>
    

    请注意,没有显示“立即触摸...”消息,但输出文件的时间戳(2014-11-26 00:44:09.7744589)已经比输入文件的时间戳更新(2014-11- 26 00:44:09.078676)这是 BEFORE 第一个构建目标运行!实际上,当我建立诊断详细程度时,它告诉我输出是关于输入的最新信息!

    现在看看使用msbuild构建时会发生什么:

    PS C:\work\a> .\1.ps1 -msbuild
    in.txt : 2014-11-26 00:44:15.854564
    Microsoft (R) Build Engine version 4.0.30319.34209
    [Microsoft .NET Framework, version 4.0.30319.34209]
    Copyright (C) Microsoft Corporation. All rights reserved.
    
      out.txt : 2014-11-26 00:44:09.7744589
      Touching now ...
      a -> C:\work\a\bin\Debug\a.dll
    PS C:\work\a>
    

    一切都符合预期 - 输出文件时间戳(2014-11-26 00:44:09.7744589)早于输入文件(2014-11-26 00:44:15.854564)。因此,打印出“立即触摸...”消息。

    注意,我在安全模式下运行devenv。我正在使用VS2012。

    编辑1

    挂钩CoreBuildDependsOn会产生预期结果:

    <CoreBuildDependsOn>$(CoreBuildDependsOn);MyTarget</CoreBuildDependsOn>
    

    结果是:

    PS C:\work\a> .\1.ps1
    in.txt : 2014-11-26 12:55:56.787793
    
    Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0.
    Copyright (C) Microsoft Corp. All rights reserved.
    1>------ Build started: Project: a, Configuration: Debug Any CPU ------
    1>  out.txt : 2014-11-26 12:54:29.8173007
    1>  a -> C:\work\a\bin\Debug\a.dll
    1>  Touching now ...
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
    PS C:\work\a>
    

    请注意“正在触摸...”消息以及构建之前的out.txt时间戳早于in.txt的时间戳 - 正如预期的那样。

    结论:de {{Compile目标在后台由devenv静默调用,而不是CoreBuild。为什么会这样?

1 个答案:

答案 0 :(得分:1)

找到了这个 - https://social.msdn.microsoft.com/Forums/en-US/bf86d834-0e48-42ff-b2e4-5f930597bef0/background-compilation-in-visual-c?forum=csharpide

所以,答案是我们无法阻止后台编译,但我们的自定义编译目标可以通过测试BuildingProject属性来防御性地编写。或者似乎,因为我实际上没有测试它,将逻辑移动到CoreBuild依赖关系似乎对我来说已经足够了。