I'm using MSBuild for our CI process and I'm trying to find a way to get the folder name of a folder higher up in the filesystem hierarchy. This folder would hold all the tools for the CI.
The folder I'm looking for can be located at various places on each PC.
Let's say that the MSBuild script is executing in the D:\Workdir\BlaBla\Project1 and the folder I'm interested in is D:\Workdir\CI
I would like the script to traverse the filesystem as follows:
- Look in current dir (D:\WorkDir\BlaBla\Project1), check for CI folder (not found)
- Go up in the hierarchy (D:\Workdir\BlaBla) and check for CI folder (not found)
- Go up again (D:\Workdir) and check for CI folder (Found!)
Is this feasible in MSBuild?
NOTES
Just to clarify, I want to get the result (the location of the folder) in a property.
Here's what I have so far and trying to better it ;)
<PropertyGroup>
<CI_PathName Condition=" Exists ('..\CI') ">..\CI</CI_PathName >
<CI_PathName Condition=" Exists ('..\..\CI') ">..\..\CI</CI_PathName >
<CI_PathName Condition=" Exists ('..\..\..\CI') ">..\..\..\CI</CI_PathName >
</PropertyGroup>
This wo开发者_运维技巧rks but it is not optimal...
You can do this using an inline task:
<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask
TaskName="FindParentDirectory"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<BaseDirectory ParameterType="Microsoft.Build.Framework.ITaskItem" Required="true" />
<TargetDirectoryName ParameterType="System.String" Required="true" />
<TargetDirectory ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO" />
<Code Type="Fragment" Language="cs">
<![CDATA[
string baseDirectoryPath = BaseDirectory.GetMetadata("FullPath");
DirectoryInfo baseDirectory = new DirectoryInfo(baseDirectoryPath);
DirectoryInfo[] childDirectories = baseDirectory.GetDirectories(TargetDirectoryName);
if (childDirectories.Length == 1)
{
TargetDirectory = childDirectories[0].FullName;
return true;
}
while (baseDirectory != baseDirectory.Root)
{
baseDirectory = baseDirectory.Parent;
if (baseDirectory.Name == TargetDirectoryName)
{
TargetDirectory = baseDirectory.FullName;
return true;
}
childDirectories = baseDirectory.GetDirectories(TargetDirectoryName);
if (childDirectories.Length == 1)
{
TargetDirectory = childDirectories[0].FullName;
return true;
}
}
Log.LogError("Unable to find recursively find a directory called '{0}' in a parent of '{1}'.", TargetDirectoryName, baseDirectoryPath);
return false;
]]>
</Code>
</Task>
</UsingTask>
<Target Name="Build">
<FindParentDirectory
BaseDirectory="$(MSBuildProjectDirectory)"
TargetDirectoryName="Development">
<Output
TaskParameter="TargetDirectory"
PropertyName="TargetDir" />
</FindParentDirectory>
<Message
Text="TargetDir = '$(TargetDir)'"
Importance="high" />
</Target>
Yes, you can use the "Exec" tag and set its "Command" attribute in any Target of MS Build. Open the project file in text mode and you can add your command inside the Target that you might want (for example, Target "BeforeBuild", if you want your script to be executed before the Build)
EDIT:
Open your project file in text mode, navigate to the section: <Target Name="BeforeBuild">. Add the Exec node within this Target Node. Once you are done your Target node might look like this:
<Target Name="BeforeBuild">
<Exec Command="yourscript or any DOS command" />
... if you had anything before in this section leave them as is
</Target>
精彩评论