MSBuild项包含(通配符)不扩展

And*_*tan 23 c# msbuild visual-studio-2012

这很奇怪.我们一直试图弄清楚它,但它确实没有任何意义.

我们的Web项目导入目标文件,其目标类似于:

<Target Name="CSSCheckInternal">
    <ItemGroup>
        <CSSFiles Include="$(MSBuildProjectDirectory)\**\*.css" />
    </ItemGroup>
    <CSSChecker Files="@(CSSFiles)" />
</Target>
Run Code Online (Sandbox Code Playgroud)

目前,一个分支正在完美建设,按要求执行任务; 但是另一个分支在上述目标上失败了.

失败的原因是@(CSSFiles),当任务收到该项时,该项似乎不会扩展为ITaskItem数组.

该任务编写如下(直到我获得FullPath元数据):

public class CSSChecker : Task
{
    [Required]
    public ITaskItem[] Files
    {
        get;
        set;
    }

    public override bool Execute()
    {
        string fullFilePath = null;
        if (Files != null)
        {
            foreach (var item in Files)
            {
                fullFilePath = item.GetMetadata("FullPath");
                if(!File.Exists(fullFilePath))
                  throw new InvalidOperationException(
                   string.Format("{0} does not exist", fullFilePath));


        //rest of the code elided
Run Code Online (Sandbox Code Playgroud)

失败的构建是抛出InvalidOperationException最后一行,如下所示:

文件不存在:C:\ Code\Project\**\*.css

因此,似乎MSBuild不是在Include属性中扩展通配符,而只是将字符串传递过来,因此ITaskItem在任务上只创建一个.

目标文件夹确实存在于磁盘上,并且损坏的项目文件与工作文件之间的唯一区别是单个文件包含在项目文件的更早版本中.

更新

在推特上写了Sayed Hashimi(编写了MSBuild书)并通过它,尝试取出**文件夹通配符,现在它开始工作了.这不太合适,因为任务可以在项目之间重复使用.但它似乎与此有关.

结束更新

如果有人知道MSBuild在什么情况下不能正确扩展通配符,那将是一个很大的帮助!

And*_*tan 20

我已经想到了这一点 - 我必须删除项目目录中的obj \文件夹,突然文件夹通配符再次开始工作.

对我的情况简短的回答是,如果任何路径太长,MSBuild的通配符处理代码就会完全崩溃,而且只是没有构建一个项目组.

这里的事情是我如何设法创建那么长的路径?好吧,我没有.这是内置的Web发布任务 - 我这样使用(对于我们自己的自定义部署):

<MSBuild Projects="$(Proj)" Properties="Platform=$(Platform);
 Configuration=$(Configuration);DeployOnBuild=true;PackageAsSingleFile=False;
 AutoParameterizationWebConfigConnectionStrings=False" />
Run Code Online (Sandbox Code Playgroud)

当你这样做PackageAsSingleFile=False,我用来阻止构建zip,因为我想要网站可部署,在obj文件夹中你得到一个像这样的文件夹结构:

[Project_Dir]\obj\[configuration]\Package\PackageTemp\[Project Dir]\[output *]
Run Code Online (Sandbox Code Playgroud)

如果是[Project_Dir] c:\my project\,那么临时包文件的基本文件夹就是这样的c:\my project\obj\debug\Package\PackageTemp\c_c\my project\.

正如您所看到的,这已经是一个非常深的文件夹结构,实际上项目通常不是驱动器根目录上的顶级文件夹.

我发现,在我们的一些使用此部署方法的项目中,无法obj\在资源管理器或命令行中删除该文件夹,因为路径太长.我要做的就是根据需要重命名尽可能多的父文件夹1,以便缩短完整路径,然后执行删除操作.即在前面的例子中,我将重命名如下:

c:\my project\obj\1\1\1\1\1
Run Code Online (Sandbox Code Playgroud)

哪个效果很好.

你可以想象 - 如果项目在一个足够深的文件夹中开始 - 那么为发布任务生成的项目的最终路径将变得非常长.我发现,如果我只是Publish在VS中使用任务,这实际上会在发布期间导致错误 - 但它似乎以我上面显示的方式炮轰MSBuild,实际上以某种方式回避文件夹最大路径限制.我打算组建一个很快证明这一点的项目.

因此,在我的情况下,我必须重写我的任务以获取要处理的基本文件夹,然后让它通过文件夹和文件本身进行递归,忽略它找到的任何"obj"文件夹.

我尝试使用'Exclude'属性排除 obj文件夹中的任何文件,但它没有任何区别(大概是因为两者都出了问题!).


Sco*_*nro 7

我有同样的问题,可以确认它也与长路径有关.我在node_modules文件夹中,由npm管理.

我发现我可以删除长路径而不必重命名文件夹,因为Andreas使用了rimraf工具.如果您遇到任何错误,请再次尝试.

另外,如果它实际上不是您感兴趣的真正递归 - 比如说您只使用双星号(**)语法作为包含三个文件夹级别的快捷方式 - 那么您可以用一系列文件替换双星号语法表达式使用单个星号(*).

例如,假设实际上只需要包含三个级别的文件夹,您可以交换此...

C:\**\*.*
Run Code Online (Sandbox Code Playgroud)

...为了这.

C:\*\*.*
C:\*\*\*.*
C:\*\*\*\*.*
Run Code Online (Sandbox Code Playgroud)


pau*_*ulm 5

只有在递归搜索中的任何路径长于时,才会出现此问题MAX_PATH.您可以通过尝试使用资源管理器在最深的路径中创建目录来检查这一点,您将收到一条错误消息,告诉您路径太长并且无法创建目录.或者,如果要重现此问题,请使用CreateFileW()扩展\\\?\路径语法创建比使用最大路径长的路径.

MsBuild必须在FindNextFile()再次调用之前在内部检查长度,因为你从未在procmon中看到任何路径太长的错误.您将看到的是,在路径太长之前它只是获得预期的一级ERROR_NO_MORE_FILES,然后关闭搜索句柄,但是甚至不打算尝试下一级.一旦发生这种情况,MsBuild将放弃其枚举,没有错误!