How to turn off caching of build definitions in Vi

2019-01-09 01:30发布

问题:

In project file I import my own target file

<Import Project="Build\CopyDependencies.target" />

and later I call target from that target file

<CallTarget Targets="CopyDependencies" UseResultsCache="false" />

If I edit CopyDependencies.target file I have to reload whole solution and only then changes to CopyDependencies.target take effect. I believe it is some sort of build definitions caching in Visual Studio? If it is, maybe it can be turned off?

回答1:

Thanks @KazR

Here is a smaller Solution that you can insert into your .csproj file

<Target Name="AfterBuild">
  <PropertyGroup>
    <TempProjectFile>Build.$([System.Guid]::NewGuid()).proj</TempProjectFile>
  </PropertyGroup>
  <Copy SourceFiles="Build.proj" DestinationFiles="$(TempProjectFile)" />
  <MSBuild Projects="$(TempProjectFile)" />
  <ItemGroup>
    <TempProjectFiles Include="Build.????????-????-????-????-????????????.proj"/>
  </ItemGroup>
  <Delete Files="@(TempProjectFiles)" />
</Target>

Problem solved



回答2:

I don't know how you would disable the VS cache, however I may have a workaround that would allow you to edit the build target without having to reload the solution.

You could use the MSBuild task in your proj file to call a wrapper target that copies your CopyDependencies.target file to CopyDependencies.[RandomNumber].target, then invokes your CopyDependencies target in the newly created file, and finally deletes it.

This would force VS to reload the target on each invocation as the filename is different.

Here's an example:

myProject.proj

Add this to the AfterBuild target:

<MSBuild Projects="Wrapper.target" Targets="MyWrappedTarget" UnloadProjectsOnCompletion="true"/>

Wrapper.target

Here we have the target that will - at build time - copy the real target file and invoke the desired build target within it (I've used an inline c# task which is only available in MSBuild 4.0):

    <UsingTask TaskName="RandomNumber" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <Number ParameterType="System.Int32" Output="true"/>
    </ParameterGroup>
    <Task>
        <Code Type="Fragment" Language="cs">
        <!-- CDATA -->
        Random rndGenerator = new Random();
        Number = rndGenerator.Next(Int32.MaxValue);
        <!-- CDATA -->
        </Code>
    </Task>
</UsingTask>

<Target Name="MyWrappedTarget">
    <Message Text="MyWrappedTarget target called"/>


    <RandomNumber>
        <Output TaskParameter="Number" PropertyName="FileNumber"/>
    </RandomNumber>

    <PropertyGroup>
        <CopiedTarget>inner.test.$(FileNumber).target</CopiedTarget>
    </PropertyGroup>

    <Copy SourceFiles="inner.test.target" DestinationFiles="$(CopiedTarget)"/>

    <MSBuild Projects="$(CopiedTarget)" Targets="_innerTestTarget"/>

    <Delete Files="$(CopiedTarget)"/>
</Target>

inner.test.target

This contains the real build target you want to execute, in this example it's a simple file copy.

    <Target Name="_innerTestTarget">

    <Message Text="This is a inner test text message"/>
    <Copy SourceFiles="x.txt" DestinationFiles="x1.txt"/>
</Target>

This isn't production ready, but hopefully illustrates my point.

With this (slightly convoluted) process in place, you can change the inner.test.target file without having to reload the solution in VS.



回答3:

I have a different solution, not involving temporary files:

Include.targets file:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <Target Name="Foobar">
      <Copy SourceFiles="test.source" DestinationFiles="testFoobar.dest" />
   </Target>

</Project>

Project file:

....
<Target Name="BeforeBuild">
    <Exec Command="$(MSBuildToolsPath)\MSBuild.exe Include.targets /t:Foobar" ContinueOnError="false" />
</Target>
....

in this case VS does not recognize the MSBuild command, and does not cache the file.

happy coding!



回答4:

Here's a solution that doesn't require any MSBuild scripting at all.

I noticed that unloading and reloading a project doesn't get around the cache, but closing and reopening the solution does. In addition, Visual Studio will prompt you to reload the solution if it notices the .sln file has changed. And finally, this superuser question explains how to touch a file in Windows.

Putting these together, I added a Visual Studio external tool to touch the current solution file. Here's how:

  1. Select TOOLS > External Tools ...
  2. Click the Add button to add a new tool.
  3. Set properties as follows:
    • Title: Reload Solution
    • Command: cmd.exe
    • Arguments: /c copy "$(SolutionFileName)"+>nul
    • Initial directory: $(SolutionDir)
    • and turn on Use Output window
  4. Click OK to close the External Tools window

Now if you have made changes to your MSBuild files, just select TOOLS > Reload Solution and all your build files will be reloaded.

I'm using Windows 7 64-bit and Visual Studio 2012 Express for Windows Desktop.



回答5:

Before running MSBuild I run this to clear the download cache:

call "%VS120COMNTOOLS%vsvars32.bat"
echo Clear download cache
gacutil -cdl