Как предотвратить devenv от тихого вызова цели Compile в фоновом режиме?

Я заметил, что когда я запускаю 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.

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>

Обратите внимание, что сообщение "Touching now ..." не отображается, однако временная метка выходного файла (2014-11-26 00:44:09.7744589) уже новее, чем у входного файла (2014-11-26 00:44:09.078676) и это ДО того, как будет запущена самая первая цель сборки! Действительно, когда я встраиваю уровень подробности диагностики, он говорит мне, что результаты являются актуальными по отношению к входам!

Теперь посмотрим, что происходит, когда я собираю с помощью 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>

Обратите внимание на сообщение "Touching now ..." и отметку времени out.txt до того, как сборка будет старше, чем в in.txt - как и ожидалось.

Вывод: Compile цель молча вызывается devenv на заднем плане, но не CoreBuild, Почему это так?

1 ответ

Нашел это - https://social.msdn.microsoft.com/Forums/en-US/bf86d834-0e48-42ff-b2e4-5f930597bef0/background-compilation-in-visual-c?forum=csharpide

Таким образом, ответ в том, что мы не можем предотвратить фоновую компиляцию, но наши собственные цели компиляции могут быть написаны для защиты, протестировав BuildingProject имущество. Или, похоже, поскольку я на самом деле не проверял это, перемещение логики в зависимость от CoreBuild кажется мне достаточно хорошим.

Другие вопросы по тегам