gpt4 book ai didi

MSBuild 项目无法在 MSBuild 任务中使用,错误 MSB4012

转载 作者:行者123 更新时间:2023-12-02 17:52:58 24 4
gpt4 key购买 nike

我有以下 MSBuild 项目文件:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Deploy" ToolsVersion="4.0">
<ItemGroup>
<Base Include="$(MSBuildProjectDirectory)\.." />
</ItemGroup>

<PropertyGroup>
<BaseDirectory>@(Base->'%(FullPath)')</BaseDirectory>
<DeployDirectory>$(BaseDirectory)\Deploy</DeployDirectory>
<Configuration>Release</Configuration>
</PropertyGroup>

<Target Name="Deploy" DependsOnTargets="Hello;Clean;Build" />

<Target Name="Hello">
<Message Text="Hello world. BaseDirectory=$(BaseDirectory), DeployDirectory=$(DeployDirectory)" />
</Target>

<Target Name="Clean">
<RemoveDir Directories="$(DeployDirectory)" />
</Target>

<Target Name="Build">
<MSBuild Projects="$(BaseDirectory)\DebugConsoleApp\DebugConsoleApp.csproj" Properties="Configuration=$(Configuration);OutputPath=$(DeployDirectory)" ContinueOnError="false" />
</Target>

</Project>

当我运行它时,出现错误:

C:\Repositories\Project\Build\Build.proj(22,16): error MSB4012: The expression "@(Base->'%(FullPath)')\Deploy" cannot be used in this context. Item lists cannot be concatenated with other strings where an item lis t is expected. Use a semicolon to separate multiple item lists.

为什么会出现此错误以及如何避免?我在 ItemGroup 中使用 item Base ,因为我需要删除路径中的 .. ,并且 Items 允许通过 %FullPath 元数据来完成此操作。如果我只使用 PropertyGroup 那么一切工作正常,但我在所有路径中都有这个 ..

最佳答案

很难准确说出幕后发生的事情。我不在 MSBuild 上,所以我对实际的实现只是不太熟悉。我们需要 MSBuild 开发人员来提供 100% 正确的答案。但这是我假设正在发生的事情(请阅读:其余部分包含我的猜测)。

当你使用语句时你的目标内部

Projects="$(BaseDirectory)\DebugConsoleApp\DebugConsoleApp.csproj"

MSBuild 注意到您使用了属性扩展 $(BaseDirectory),并且 MSBuild 上项目的参数类型是数组。 MSBuild 还注意到 BaseDirectory 是一个包含项目的属性。这些属性的行为与普通属性不同。您可以将它们视为“虚拟属性(property)”(是的,我刚刚创造了这个术语)。当使用这些属性而不是查找值时,会进行内联替换。因此您的 Projects 属性更改为:

Projects="@(Base->'%(FullPath)')\DebugConsoleApp\DebugConsoleApp.csproj" 

由于 Projects 是一个数组,MSBuild 将尝试对提供的表达式执行转换。由于这不是有效的转换,因此会发生错误。这是您收到的错误。

现在要解决此问题,您可以将构建目标更改为如下所示:

<Target Name="Build">
<PropertyGroup>
<_BaseDir>$(BaseDirectory)</_BaseDir>
<_DeployDir>@(Base->'%(FullPath)')</_DeployDir>
</PropertyGroup>

<Message Text="_BaseDir: $(_BaseDir)"/>
<Message Text="DeployDirectory: $(DeployDirectory)"/>

<MSBuild Projects="$(_BaseDir)\DebugConsoleApp\DebugConsoleApp.csproj"
Properties="Configuration=$(Configuration);OutputPath=$(_Tmp2)"
ContinueOnError="false" />
<!--<MSBuild Projects="$(BaseDirectory)\DebugConsoleApp\DebugConsoleApp.csproj"
Properties="Configuration=$(Configuration);OutputPath=$(DeployDirectory)"
ContinueOnError="false" />-->
</Target>

通过这种方法,我在目标本身内创建了一个属性组,并将这些“虚拟属性”的值分配给新属性。这些新属性不是虚拟属性,而是真实属性,因此您可以按照预期使用它们,不会出现任何问题。

现在回答你的问题,“为什么消息任务会起作用 WTF?!!!”在 Hello 目标中,您有以下内容:

<Message Text="Hello world. BaseDirectory=$(BaseDirectory), DeployDirectory=$(DeployDirectory)" />

没有任何问题。之前我提到过,这些虚拟属性本质上将被支持它们的定义内联替换,因此这实际上会变成。

<Message Text="Hello world. BaseDirectory=@(Base->'%(FullPath)'), DeployDirectory=@(Base->'%(FullPath)')\Deploy" />

好吧,保留这个想法。

MSBuild 任务上的 Text 属性定义为一个字符串,它是一个标量值。如果您还记得 MSBuild 任务上的 Projects 属性定义为 ITaskItem[],因为这是一个数组,它是一个向量值。当在向量值属性中找到@(...)时,整个表达式将用作项目转换。在这种情况下,语句 @(Base->'%(FullPath)')\DebugConsoleApp\DebugConsoleApp.csproj 不是有效的转换表达式。当在标量值属性声明中找到“@(..)”时,这些值将被展平为字符串。因此,“@(...)”的每个实例都会被处理并展平为单个字符串值。如果有多个值,则使用分隔符。

希望这能解释您所看到的行为,它实际上可能是一个错误。您可以登录http://connect.microsoft.com/ MSBuild 团队将对其进行分类。

有关虚拟属性(property)的更多信息之前我提到过,这些虚拟属性的行为与普通属性不同,因为不会查找值,而是使用属性表达式替换 $(...) 的用法。不要相信我的话,你自己看看吧。这是我创建的示例文件

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<ItemGroup>
<MyItem Include="C:\temp\01.txt"></MyItem>
</ItemGroup>

<PropertyGroup>
<MyProperty>@(MyItem->'%(FullPath)')</MyProperty>
</PropertyGroup>

<Target Name="Demo">
<Message Text="MyProperty: $(MyProperty)" />
<!-- Add to the item -->
<ItemGroup>
<MyItem Include="C:\temp\01.txt"></MyItem>
</ItemGroup>
<Message Text="MyProperty: $(MyProperty)" />
</Target>

</Project>

这里我声明了一个项目列表MyItem和一个依赖属性MyProperty。在 Demo 目标内,我打印 MyProperty 的值,然后将另一个值添加到 MyItem 项目列表,并再次打印 MyProperty 的值。这是结果。

PS C:\temp\MSBuild\SO> msbuild .\Build.proj /nologo
Build started 4/26/2011 10:17:08 PM.
Project "C:\temp\MSBuild\SO\Build.proj" on node 1 (default targets).
First:
MyProperty: C:\temp\01.txt
MyProperty: C:\temp\01.txt;C:\temp\01.txt
Done Building Project "C:\temp\MSBuild\SO\Build.proj" (default targets).

正如您所看到的,它的行为方式与我所说的一致。

关于MSBuild 项目无法在 MSBuild 任务中使用,错误 MSB4012,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5689204/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com