I'm running into an issue with MSBuild running SSDT for VS 2012, which I have forced in a .proj used for running the subtree build by the property:
<PropertyGroup><VisualStudioVersion>11.0</VisualStudioVersion></PropertyGroup>
When it executes, the build runs fine locally on a "Developer Command Prompt for 2012" cmd window using msbuild from command-line. However, during a TFS build MSBuild will emit the issue for a random .sqlproj that was built:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets (513): The process cannot access the file 'D:\Builds\...\Sources\obj\...\Release\Model.xml' because it is being used by another process.
(imagine there's some other directory paths there for the ... that I've snipped for privacy)
Other than killing my build performance by passing msbuild /m:1
to restrict to one "CPU", trying to avoid the contention on the Model.xml
file that the SqlBuildTask
creates at the end of its execution, how can I avoid this issue? I've tried to find details online but MSDN and search engines are failing to find something that is equivalent to the sqlpackage.exe parameter, Storage=Memory
, which suggests it doesn't make the Model.xml
file and instead uses memory.
For reference, I am generating a .dacpac output from my build such that I can use it to publish to a any database later and upgrade it to latest (using aforementioned sqlpackage.exe on the command-line with the /a:Publish
command).
I found the following MSDN article useful in fixing this issue: Common MSBuild Project Properties
In my project file I had the following (snipping out the non-relevant bits here such as the files in the project in ItemGroup
's):
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(DepotRoot)\internal\infrastructure\build\BuildDbProj.prop" />
<PropertyGroup>
<Name>FooDatabase</Name>
</PropertyGroup>
I altered the prop file such that it now has an IntermediateOutputPath (the other bits were already there), which now looks like:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="Build.prop" />
<PropertyGroup>
<OutputPath>$(FullOutputPath)Databases\$(Name)\</OutputPath>
<IntermediateOutputPath>$(FullIntermediateOutputPath)\$(Name)</IntermediateOutputPath>
<DeploymentPath>$(FullOutputPath)Deployment\DB\$(Name)\</DeploymentPath>
<DeploymentContentPath>$(DeploymentPath)Content\</DeploymentContentPath>
</PropertyGroup>
</Project>
The relevant bits of the Build.prop
file look like:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BranchRoot>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), branch.root))\</BranchRoot>
<BranchingFolderStructure>$(BranchRoot.Replace($(DepotRoot)\internal\, ``))</BranchingFolderStructure>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' == ''">$(DepotRoot)\obj\$(BranchingFolderStructure)</BaseIntermediateOutputPath>
<FullIntermediateOutputPath Condition="'$(FullIntermediateOutputPath)' == ''">$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)</FullIntermediateOutputPath>
</PropertyGroup>
</Project>
What this now does is redirect the Model.xml to output to the D:\Builds\...\Sources\obj\...\Debug\AnyCPU\FooDatabase
directory, where FooDatabase
is the Name
property in the database project. Now I don't need to change the MSBuild to use BuildInParallel
set to False, etc.