我正在开发一个可重用的MSBuild Target,它将被其他几个任务使用。此目标要求定义多个属性。验证属性是否已定义的最佳方法是什么,如果不是,则抛出错误?
我几乎的两次尝试:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="3.5" DefaultTarget="Release" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Release">
<Error
Text="Property PropA required"
Condition="'$(PropA)' == ''"/>
<Error
Text="Property PropB required"
Condition="'$(PropB)' == ''"/>
<!-- The body of the task -->
</Target>
</Project>
这是一次批量尝试。由于额外的“名称”参数,这很难看。是否可以使用Include属性?
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="3.5" DefaultTarget="Release" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Release">
<!-- MSBuild BuildInParallel="true" Projects="@(ProjectsToBuild)"/ -->
<ItemGroup>
<RequiredProperty Include="PropA"><Name>PropA</Name></RequiredProperty>
<RequiredProperty Include="PropB"><Name>PropB</Name></RequiredProperty>
<RequiredProperty Include="PropC"><Name>PropC</Name></RequiredProperty>
</ItemGroup>
<Error
Text="Property %(RequiredProperty.Name) required"
Condition="'$(%(RequiredProperty.Name))' == ''" />
</Target>
</Project>
答案 0 :(得分:17)
好问题!我已在book和博文Elements of Reusable MSBuild Scripts: Validation中深入探讨了这一点。我的方法将涵盖属性和项目。
这是向下跑。在共享.targets文件中创建验证目标,这应该是文件中声明的第一个目标之一,以便用户可以轻松找到它。
<强>属性强>
在验证目标内定义您的属性,如下所示:
<_RequiredProperties Include="Root">
<Value>$(Root)</Value>
</_RequiredProperties>
我将属性的名称放在include及其Value
元数据中的值中。我这样做的原因是我可以检测到Value
何时为空,然后我使用include值,用于向用户报告缺失属性的名称。
<强>项
在目标内部,将所需项目放在项目中,如:
<_RequiredItems Include="AllConfigurations">
<RequiredValue>@(AllConfigurations)</RequiredValue>
</_RequiredItems>
与属性类似,在include中放置项的名称,然后在RequiredValue
元数据内部检查值。在此示例中,它仅检查以确保AllConfiguraitons
项不为空。如果要确保在所有项目上指定给定的元数据值,请执行以下操作:
<_RequiredItems Include = "AllConfigurations.Configuration">
<RequiredValue>%(AllConfigurations.Configuration </RequiredValue>
</_RequiredItems>
如果要确保文件存在,请添加其他元数据RequiredFilePath。
<_RequiredItems Include ="ProjectsToBuild">
<RequiredValue>%(ProjectsToBuild.Identity)</RequiredValue>
<RequiredFilePath>%(ProjectsToBuild.Identity)</RequiredFilePath>
</_RequiredItems>
验证
以下是执行验证所需的内容
完整示例
以下是完整示例
<Target Name="ValidateBuildSettings">
<ItemGroup>
<_RequiredProperties Include="Root">
<Value>$(Root)</Value>
</_RequiredProperties>
<_RequiredProperties Include="BuildInstallRoot">
<Value>$(BuildInstallRoot)</Value>
</_RequiredProperties>
<_RequiredProperties Include="SourceRoot">
<Value>$(SourceRoot)</Value>
</_RequiredProperties>
<!--
_RequiredItems is the item where required items should be placed.
The following metadata is significant:
REQUIRED METADATA:
Identity = This will basically be used to identify the specific required item
RequiredValue = This is the specific value that will be validated to exist
OPTIONAL METADATA
RequiredFilePath = Populate this with a path that should exists, if it is not empty
then it will be checked to exist on disk.
-->
<_RequiredItems Include="AllConfigurations">
<RequiredValue>@(AllConfigurations)</RequiredValue>
</_RequiredItems>
<_RequiredItems Include = "AllConfigurations.Configuration">
<RequiredValue>%(AllConfigurations.Configuration </RequiredValue>
</_RequiredItems>
<_RequiredItems Include ="ProjectsToBuild">
<RequiredValue>%(ProjectsToBuild.Identity)</RequiredValue>
<RequiredFilePath>%(ProjectsToBuild.Identity)</RequiredFilePath>
</_RequiredItems>
</ItemGroup>
<!-- Raise an error if any value in _RequiredProperties is missing -->
<Error Condition =" '%(_RequiredProperties.Value)'=='' "
Text=" Missing required property [%(_RequiredProperties.Identity)]" />
<!-- Raise an error if any value in _RequiredItems is empty -->
<Error Condition = " '%(_RequiredItems.RequiredValue)'=='' "
Text = " Missing required item value [%(_RequiredItems.Identity)] " />
<!-- Validate any file/directory that should exist -->
<Error Condition = " '%(_RequiredItems.RequiredFilePath)' != '' and !Exists('%(_RequiredItems.RequiredFilePath)') "
Text = " Unable to find expeceted path [%(_RequiredItems.RequiredFilePath)] on item [%(_RequiredItems.Identity)] " />
</Target>