使用MSBuild,如何将变量设置为文件系统层次结构中较高的文件夹名?
我正在为CI进程使用MSBuild,并试图找到一种方法来获取文件系统层次结构中较高层次的文件夹的文件夹名。此文件夹将保存CI的所有工具 我要找的文件夹可以放在每台电脑的不同位置 假设MSBuild脚本在D:\Workdir\BlaBla\Project1中执行,我感兴趣的文件夹是D:\Workdir\CI 我希望脚本按如下方式遍历文件系统:使用MSBuild,如何将变量设置为文件系统层次结构中较高的文件夹名?,msbuild,Msbuild,我正在为CI进程使用MSBuild,并试图找到一种方法来获取文件系统层次结构中较高层次的文件夹的文件夹名。此文件夹将保存CI的所有工具 我要找的文件夹可以放在每台电脑的不同位置 假设MSBuild脚本在D:\Workdir\BlaBla\Project1中执行,我感兴趣的文件夹是D:\Workdir\CI 我希望脚本按如下方式遍历文件系统: 查找当前目录(D:\WorkDir\BlaBla\Project1),检查CI文件夹(未找到) 进入层次结构(D:\Workdir\BlaBla)并检查CI
笔记 为了澄清,我想在属性中获得结果(文件夹的位置)
以下是我到目前为止所拥有的并试图改进的内容;)
..\CI
..\..\CI
..\..\..\CI
这是可行的,但不是最优的…是的,您可以在MS Build的任何目标中使用“Exec”标记并设置其“Command”属性。以文本模式打开项目文件,您可以将命令添加到您可能需要的目标中(例如,如果您希望在生成之前执行脚本,则添加目标“BeforeBuild”)
编辑:
以文本模式打开项目文件,导航到以下部分:。在此目标节点中添加Exec节点。完成后,目标节点可能如下所示:
<Target Name="BeforeBuild">
<Exec Command="yourscript or any DOS command" />
... if you had anything before in this section leave them as is
</Target>
... 如果您以前在本节中有任何内容,请保持原样
您可以使用内联任务执行此操作:
<?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>
hmmm。。。我不太明白。你能澄清一下吗?我想你希望你的脚本在构建之前被执行,对吗?如果是,请继续阅读编辑(我无法格式化此“注释”中的代码部分)。好的,我想获取文件夹的位置;)您可以创建一个批处理来处理查找CI文件夹的要求吗?当然可以,但我想知道是否有一种仅使用MSBuild的方法。太好了!我不知道我能做到!
<?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>