问题描述:

I've been told that the following should create an ItemGroup of files with meta data saying whether they are read only or not:

<?xml version="1.0" encoding="utf-8"?>

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"

DefaultTargets="Run"

ToolsVersion="12.0">

<Target Name="Main">

<ItemGroup>

<MyFiles Include="test.proj"> <!-- also tried with *.*. Using test.proj (this file) to be sure it is a file that exists -->

<ReadOnly Condition='1 == $([MSBuild]::BitwiseAnd(1, $([System.IO.File]::GetAttributes("%(Identity)"))))'>True</ReadOnly>

</MyFiles>

</ItemGroup>

</Target>

<Target Name="Run" Outputs="%(MyFiles.Identity)" DependsOnTargets="Main">

<Message Text="%(MyFiles.Identity) Not ReadOnly" Condition="%(MyFiles.ReadOnly) != True"/>

<Message Text="%(MyFiles.Identity) ReadOnly" Condition="%(MyFiles.ReadOnly) == True" />

</Target>

</Project>

However, I get the following output (when run from a Developer Command Prompt for Visual Studio 2013):

S:\>msbuild test.proj

Microsoft (R) Build Engine version 12.0.30723.0

[Microsoft .NET Framework, version 4.0.30319.34014]

Copyright (C) Microsoft Corporation. All rights reserved.

Build started 30/10/2014 21:18:46.

Project "S:\test.proj" on node 1 (default targets).

S:\test.proj(9,13): error MSB4184: The expression "[System.IO.File]::GetAttributes('')" cannot be evaluated. The path is not of a legal form.

Done Building Project "S:\test.proj" (default targets) -- FAILED.

Build FAILED.

"S:\test.proj" (default target) (1) ->

(Main target) ->

S:\test.proj(9,13): error MSB4184: The expression "[System.IO.File]::GetAttributes('')" cannot be evaluated. The path is not of a legal form.

0 Warning(s)

1 Error(s)

Time Elapsed 00:00:00.01

S:\>

Should this work? If so, where am I going wrong?

网友答案:

It appears that you can't reference Item Metadata when creating an ItemGroup from within a target.

Changing your script to:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="Run"
         ToolsVersion="12.0">

<ItemGroup>
    <MyFiles Include="test.proj" >
        <ReadOnly Condition='1 == $([MSBuild]::BitwiseAnd(1, $([System.IO.File]::GetAttributes("%(Identity)"))))'>True</ReadOnly>
    </MyFiles>
</ItemGroup> 

<Target Name="Run" Outputs="%(MyFiles.Identity)">
  <Message Text="%(MyFiles.Identity) Not ReadOnly" Condition="%(MyFiles.ReadOnly) != True"/>
  <Message Text="%(MyFiles.Identity) ReadOnly" Condition="%(MyFiles.ReadOnly) == True" />
</Target>

</Project>

Will produce the following output:

D:\temp\test>"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" test1.msbuild /t:run
Microsoft (R) Build Engine version 12.0.30723.0
[Microsoft .NET Framework, version 4.0.30319.18444]
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 10/30/2014 4:31:35 PM.
Project "D:\temp\test\test1.msbuild" on node 1 (run target(s)).
Run:
  test.proj Not ReadOnly
Done Building Project "D:\temp\test\test1.msbuild" (run target(s)).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.17

D:\temp\test>

You can change your script to this if all your items are guaranteed to exist before the script runs. However, I suspect since you are using it from within a target that they don't. In which case you might have to resort to the CreateItem task.

相关阅读:
Top