I have a target that I pass an ItemGroup to. I then call a task that takes this ItemGroup as a parameter and a ITaskItem as another parameter.
Sometimes, if I pass an ITaskItem[] to the ITaskItem parameter, MSBuild is clever enough to realise that I want the task called once for each item in the ItemGroup.
Most of the time, however, I get this error: Multiple items cannot be passed into a parameter of type "Microsoft.Build.Framework.ITaskItem"
Anyone any ideas why this behaviour would be so random

Random behaviour with ITaskItem[]
Derek Knudsen
Thanks, Sumedh
Interestingly, I fixed the problem by actually reading the documentation on batching and removing the transform from the OutputFile attribute.
<Target Name="Compile" Inputs="@(Compile);"
Outputs="@(Compile -> '%(Filename)$(OutputExtension)')"
DependsOnTargets="$(CompileDependsOn)">
<Task
SourceFiles="@(Compile)"
OutputFile="$(IntermediateOutputPath)%(Filename)$(IntermediateExt)"/>
</Target>
I am convinced, however that the malformed Outputs parameter shouldn't have caused that behaviour, and is probably a bug!
tropics43
Can you tell me what items are in the @(Compile) list. Just one item or multiple items
Can you also tell me what the values are of the properties $(xxx) in the snippet above. I want to try and reproduce/debug this.
Steve010010101111101010011111111
Nagendra Rao S.V
Michael,
Can you please log this issue along with the details of your investigation through the MSDN Product Feedback Center (http://lab.msdn.microsoft.com/productfeedback/default.aspx) This will get it into our bug database and we can investigate a fix for our next release.
Neil
Deathra
Hi Michael,
This is hard to believe, but this behaviour is actually "by design". Of course, we intend to fix this "design". Thanks for logging a bug via MSDN.
The issue, of course, is the incorrectly formatted transform in the Outputs attribute. Because the Outputs transform is incorrectly formatted for the "Bug" target, we ignore the transform and pick up just the correctly formatted %(Filename) instead. This causes target batching, and the one-by-one behaviour, which is what the task expects.
The fix would be to detect the incorrect transform and error out so you know what's going on. And then the right action for the user would be to move the batching onto the task (which is what you've done).
Thanks!
--Sumedh
Siang
No problem.
This has been filed as bug number FDBK46603 - "Improperly formed Outputs parameter causes strange batching behaviour"
LoneStar
Sumedh, it doesn't matter what the values of the properties are. I can reproduce the error with the following:
<
xml version="1.0" encoding="utf-8" ><Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<ItemGroup>
<Test Include="c:\windows\*.dll" />
</ItemGroup>
<
UsingTask TaskName="MyTask" AssemblyFile="MyTask.dll" /><
Target Name="Build" Inputs="@(Test)" Outputs="@(Test->'c:\test\%(FileName).txt')"><MyTask Files ="@(Test)" FileToCreate="@(Test->'c:\test\%(FileName).txt')" />
</Target>
<
Target Name="Bug" Inputs="@(Test)" Outputs="@(Test->'c:\test\%(FileName).txt'"><MyTask Files ="@(Test)" FileToCreate="@(Test->'c:\test\%(FileName).txt')" />
</Target>
</
Project>Where MyTask looks like this:
public class MyTask:Task{
private ITaskItem[] files; public ITaskItem[] Files
{
get { return files; }
set { files = value; }
} private ITaskItem fileToCreate; public ITaskItem FileToCreate
{
get { return fileToCreate; }
set { fileToCreate = value; }
}
public override bool Execute()
{
Log.LogCommandLine(fileToCreate.ItemSpec);
return true;
}
}
Running the Build target will throw an error, whereas the Bug target will use batching and pass the test. The only difference between the two targets is the improperly terminated Outputs parameter.
Hope that helps you track down the problem.
aniscartujo
Okay, it appears to be related to transforms and the Outputs parameter.
If I specify the target like this:
<
Target Name="Compile" Inputs="@(Compile);"Outputs="@(Compile -> '%(Filename)$(OutputExtension)"
DependsOnTargets="$(CompileDependsOn)">
<
TaskSourceFiles="@(Compile)"
OutputFile="@(Compile -> '$(IntermediateOutputPath)%(Filename)$(IntermediateExt)');"/>
</Target>
It works, but I lose the Outputs checking because the transform is incorrectly terminated.
<Target Name="Compile" Inputs="@(Compile);"
Outputs="@(Compile -> '%(Filename)$(OutputExtension)')"
DependsOnTargets="$(CompileDependsOn)">
<Task
SourceFiles="@(Compile)"
OutputFile="@(Compile -> '$(IntermediateOutputPath)%(Filename)$(IntermediateExt)');"/>
</Target>
When I terminate the Outputs correctly, the task fails with the error in my first post.
Interestingly, having no inputs and outputs also causes the error.
Is this a bug
Fernandob
Michael,
Why do you have a semi-colon at the end of this I think presence of the semi-colon is causing the error. (I need to look into why having a malformed Outputs on the target doesn't cause the error... I'll reply again later...)
OutputFile="@(Compile -> '$(IntermediateOutputPath)%(Filename)$(IntermediateExt)');"