问题
I have the following situation:
A SQL project in which i have a nuget package installed. This package (merely a PS script) is responsible for unpacking the DACPACs that the DB requires, using references to paths relative to the solution folder (to find the packages/ and dacpacs/ folders and to browse through the projects which it extracts from the .sln file). This is called as a pre-build event.
When building the entire solution, the $(SolutionDir) is defined, as expected (locally and ADO).
When building the test project, the $(SolutionDir) is either '' or '*Undefined*'. Again, as expected, because msbuild has no knowledge about the solution when building a single project. I can live with this caveat locally, no problem.
The question is this: is there something "magical" out there that i can use to make this work in Azure DevOps?
I can try various hacks, if anyone is aware of such methods, although i would like a clean solution.
Tried so far:
1) Adding the following PropertyGroup:
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)' == '' Or '$(SolutionDir)' == '*Undefined*'">.\</SolutionDir>
</PropertyGroup>
to the test project.
2) Following these sugestions: Prebuild event in Visual Studio replacing $(SolutionDir) with *Undefined*
No effect.
回答1:
If your folder structure is something like:
1.The Azure Devops Repos contains the solution folder(where exists the xx.sln file).
2.And those projects are under same solution folder.
You can try my script:
<PropertyGroup>
<ProjectFolder>$([System.IO.Directory]::GetParent($(ProjectDir)))</ProjectFolder>
<MySolutionDir>$([System.IO.Directory]::GetParent($(ProjectFolder)))\</MySolutionDir>
</PropertyGroup>
The $(MySolutionDir)
represents the path where your sln file and project folders exists. Same like $(SolutionDir)
, it also has the \
. So it's format looks like SomePath\
.
And it's recommended to insert my script above the script of PreBuild event. Something like:
<PropertyGroup>
<ProjectFolder>$([System.IO.Directory]::GetParent($(ProjectDir)))</ProjectFolder>
<MySolutionDir>$([System.IO.Directory]::GetParent($(ProjectFolder)))\</MySolutionDir>
It's recommended to add my script and PreBuildEvent in same propertyGroup, and mine should be in the first.
<PreBuildEvent>echo $(MySolutionDir)</PreBuildEvent>
</PropertyGroup>
Edit1:
You can also add condition on that:
<PropertyGroup>
<ProjectFolder>$([System.IO.Directory]::GetParent($(ProjectDir)))</ProjectFolder>
<MySolutionDir>$([System.IO.Directory]::GetParent($(ProjectFolder)))\</MySolutionDir>
<SolutionDir Condition="xxxx">$(MySolutionDir)</SolutionDir>
It's recommended to add my script and PreBuildEvent in same propertyGroup, and mine should be in the first.
<PreBuildEvent>echo $(MySolutionDir)</PreBuildEvent>
</PropertyGroup>
Edit2:
Hmm, I now can reproduce the issue on my side. It's quite a strange behavior and I'm not sure about the root cause of this one. But a quick workaround is to create a new PropertyGroup
to insert our custom script instead inserting it into existing PropertyGroup
from default template:
It used to be:
....
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
<ProjectFolder>$([System.IO.Directory]::GetParent($'(ProjectDir)'))</ProjectFolder>
<ParentFolder>$([System.IO.Directory]::GetParent($'(ProjectFolder)'))\</ParentFolder>
<SolutionDir Condition=" '$(SolutionDir)' == '' Or '$(SolutionDir)' == '*Undefined*' ">$(ParentFolder)</SolutionDir>
<PreBuildEvent>echo $(SolutionDir)</PreBuildEvent>
</PropertyGroup>
<Import Condition="'$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<Import Condition="'$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<ItemGroup>
<Folder Include="Properties" />
</ItemGroup>
<ItemGroup>
<Build Include="test.sql" />
</ItemGroup>
<PropertyGroup>
<PreBuildEvent>echo $(SolutionDir)</PreBuildEvent>
</PropertyGroup>
</Project>
Now change it to be:
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
</PropertyGroup>
<Import Condition="'$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<Import Condition="'$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<ItemGroup>
<Folder Include="Properties" />
</ItemGroup>
<ItemGroup>
<Build Include="test.sql" />
</ItemGroup>
<PropertyGroup>
<ProjectFolder>$([System.IO.Directory]::GetParent($(ProjectDir)))</ProjectFolder>
<ParentFolder>$([System.IO.Directory]::GetParent($(ProjectFolder)))\</ParentFolder>
<SolutionDir Condition=" '$(SolutionDir)' == '' Or '$(SolutionDir)' == '*Undefined*' ">$(ParentFolder)</SolutionDir>
<PreBuildEvent>echo $(SolutionDir)</PreBuildEvent>
</PropertyGroup>
Also, remove the extra '
in $(ProjectDir)
. It should be $(ProjectDir)
instead of $'(ProjectDir)'
and $'(ProjectFolder)'
. I also see you have two PreBuildEvent
properties, just keep the one in our custom script. After above steps, you project now works well on my side:
来源:https://stackoverflow.com/questions/61402896/substitute-for-solutiondir-in-azure-devops-ci-pipeline