用于删除文件的MSBuild Task语法


75

我正在尝试编写一个MSBuild任务,该任务将从生产构建脚本中bin文件夹中的Obj目录和PDB删除,并且似乎无法使其正常运行。

有没有人提供执行此操作或类似操作的示例,或指向使用MSBuild删除文件和目录的简单示例的链接?

Answers:


94

如果要删除整个目录,则需要RemoveDir任务:

<RemoveDir Directories="Path/To/Obj" />

如果要从bin中删除PDB文件,则需要Delete任务:

<Delete Files="Path/To/Bin/MyApp.pdb" />

请注意,您不能在Delete任务中使用通配符,因此,如果您有多个pdb文件,则必须提供一个ItemGroup作为参数。


8
RemoveDir任务参考页(见上文)说,所有的文件和子目录将被删除。
Yawar

我希望可以标记两个答案,因为到RemoveDir任务的链接向我展示了我真正缺少的是我没有取消引用OutputPath属性来查找正确的目录。用ItemGroup语法表示的响应是我需要抓取所有pdb来删除它们的方法。谢谢你们俩!
克里斯·马里西克

1
为我工作,所以谢谢,但是最好是ContinueOnError="true"为第一次重建添加属性
-pylover 2012年

1
旁注-如果路径长度超过260个字符,则RemoveDir将失败;并且您必须将Exec与rmdir一起使用。
Ondrej Svejdar '16

我一直在处理<Delete Files=...>任务,并注意到从Visual Studio进行构建时,文件被删除,并且在输出中看到了该信息。但是,当我运行它时,它具有msbuild命令行,但不会删除文件,无论输出的详细程度如何,我在输出中都看不到它。
Howiecamp '17

131

您可以先删除这些目录中的文件,然后再删除目录本身

<Target Name="SomeTarget">
    <ItemGroup>
        <FilesToDelete Include="Path\To\Obj\**\*"/>
    </ItemGroup>   
    <Delete Files="@(FilesToDelete)" />   
    <RemoveDir Directories="Path\To\Obj\" />
</Target>

1
我有Path \ To \ Obj ** \ *的@pylover路径应该是真实的文件夹路径;例如要删除的C:\ temp \ folder。那可能是它对您不起作用的原因吗?您能否提供更多详细信息,为什么它不起作用?
易卜拉欣·哈希米说

使用2012,我刚刚验证RemoveDir是否按文档所述执行操作-删除文件和文件夹。不需要额外的步骤。
dudeNumber4 2012年

@SayedIbrahimHashimi对直接方法很抱歉,但是我有您的书,但仍然无法解决此问题。stackoverflow.com/questions/25525197/…。你能帮我吗?
Blowsie 2014年

19

发布给其他可能遇到我同样问题的人。

Delete任务无法删除只读文件,而我需要这样做,因为当MSBuild从TFS获取最新信息时,这些文件被标记为只读。我使用EXEC命令删除只读文件:

<ItemGroup>
    <FileToDelete Include="c:\temp\fileToDelete.txt"/>
</ItemGroup>
<Exec Command="del /F /Q &quot;@(FileToDelete)&quot;"/>

当文件是只读的时,这是唯一对我有用的东西!(例如从TFS签出):)谢谢。
Tod Thomson 2014年

1
我有一个带通配符的ItemGroup,该通配符扩展到了太多文件(完整路径),以致del命令行太长。我的解决方案是将通配符del直接传递给而不是使用ItemGroup。
yoyo

9

只要您必须处理一个目录,发布的答案都将起作用。如果您碰巧有嵌套文件夹,RemoveDir将失败并显示Directory not empty错误。

一种稍微通用的方法也可以处理嵌套文件夹:

<Target Name="CleanOutDir">
    <ItemGroup>
        <FilesToClean Include="$(OutDir)\**\*.*" />

        <!-- Bit of .Net to get all folders and subfolders -->
        <FoldersToClean Include="$([System.IO.Directory]::GetDirectories(&quot;$(OutDir)&quot;))" />
    </ItemGroup>

    <Delete Files="@(FilesToClean)"/>
    <RemoveDir Directories="@(FoldersToClean)" />
</Target>

5

该代码太丑陋了,应该随身带一个晕机包。;-)但是速度很快,因为它没有建立要删除的文件列表等。

<Target Name="DeleteBuildFolder">
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
</Target>

需要多少个RmDir命令?足够了,因此一些RmDir命令返回“系统找不到指定的文件”,而不是“目录不为空”。如果在Windows资源管理器中打开$(BuildFolder),则在我的计算机上似乎还需要另一个RmDir。防病毒程序可能会影响RmDir,就像它偶尔会发生Subversion一样,但我宁愿拥有全面的AV保护,而不是(错误)管理排除列表。


4

也可以先从文件中删除只读属性,然后执行msbuild delete Task。

像这样:

<Target Name="DeleteFiles">
 <Message Text="Delete File" Importance="high"/>
 <Attrib Files="$(FileToDelete)" ReadOnly="false" />
 <Delete Files="$(FileToDelete)" />
</Target>`

2
似乎此处引用的Attrib任务是MSBuild社区任务项目的一部分。
Scott Munro 2013年

2

在Visual Studio 2013中,将其添加到我的.csproj文件的末尾,就在</Project>结束标记之前

<Target Name = "clean_folders" AfterTargets="Clean">
 <Exec Command = "rd /S /Q obj" />
 <Exec Command = "rd /S /Q bin" />
</Target>

起初它似乎无法正常工作,但我注意到Visual Studio(或不确定R#)已重新添加DesignTimeResolveAssemblyReferencesInput.cache到obj文件夹中,并且还重新添加了当前\bin文件夹(我在下面的不同子文件夹中有不同的内部版本\bin)。它清除了所有其他内容,包括我从导入的.csproj文件中获得的其他25个构建配置(是的,我知道)。

如果您批量重建多个配置,请小心,因为它只会抹掉之前每次重建的所有工作,而只剩下最后一个。。


1

只是为了增加我发现的皱纹。我正在使用Visual Studio2015。通过通配符删除的发布答案对我来说仍然很麻烦。 我怀疑通配符是在构建之前而不是之后进行评估的。这意味着,如果要在构建过程中创建要删除的文件,则不会发生删除。它还会导致美妙的行为,即删除在您第二次构建时就起作用,这使所有这些工作都非常有趣。

我放弃通配符。对于我正在做的事情,我知道会引起麻烦的文件,并且我正在对实际文件名进行硬编码(如果可以在项目文件内部将其称为)。


1
如果使用通配符的ItemGroup在目标内部,则应在每次执行目标时对其进行评估。在执行项目时,确实会评估项目级别的ItemGroups。
Zastai
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.