复制到输出目录可复制文件夹结构,但只想复制文件


87

我有一个VS2008,我想将某些文件从目录复制到我的/bin/文件夹中。我已将文件(位于中/common/browserhawk/)设置为“复制到输出目录”。但是,它也会复制文件夹结构:将文件复制到/bin/common/browserhawk/

如何将这些文件复制到/bin/?我不想将它们存储在网站的根目录中,以使其正确复制。

相关问题:Visual Studio编译后将.dll和.pdb添加到项目中

Answers:


59

您可以添加构建后事件以复制文件。
转到项目属性的“构建事件”选项卡,然后将以下内容添加到“构建后事件”命令行中:

copy "$(ProjectDir)\common\browserhawk\*.*" "$(TargetDir)"

如果您的项目路径中有空格,请确保包含引号。


感谢您提供的建议,因为它在VS2012中也对我有用。
2014年

2
在我的情况下,我对此做了一些修改:xcopy /s /d /y "$(ProjectDir)\stuff" "$(TargetDir)\stuff"
Danny Staple 2015年

44

由于我无法评论以前的答案,因此将解决方案放在这里:

添加到@PaulAlexander提供的内容中,将以下内容添加到您的.csproj / .vbproj文件中:

<ItemGroup>
    <AvailableItemName Include="RootContent">
      <Visible>false</Visible>
    </AvailableItemName>  
</ItemGroup>
<Target Name="AfterBuild">
    <Copy
        DestinationFolder="$(OutputPath)"
        SourceFiles="@(RootContent)"
        SkipUnchangedFiles="true"
        />  
</Target>

这样,您可以在“属性”窗口中选择“ RootContent”作为“构建操作”,并且可以通过GUI进行访问。更完整的解释:“ AvailableItemName”选项基本上会创建一个新的命名列表,您可以将项目中的项目分配到“属性”窗口中“构建操作”属性下。然后,您可以在任何您喜欢的目标中使用此新创建的列表(例如,通过“ @(RootContent)”)。


很好的答案,只是自己就成功了!
克里斯·马里西奇

另请注意,AvailableItemName如果您在VS中编辑项目文件,VS 2010(不确定较旧的版本)将抱怨是无效元素。只是忽略警告,它仍然可以工作。
亚伦诺特,2011年

2
不幸的是,这仅将文件复制到文件所属项目的输出目录中,而不复制到启动项目的输出目录中。在库项目中使用它时,这一点很重要。
塞巴斯蒂安·克里斯曼斯基2012年

2
这对于在vs2008中以发布和调试模式进行构建非常有用,但是在使用一键发布时似乎不起作用。有什么建议么?
Soenhay

2
在vs2015中不适用于我。通过稍微重写目标来解决:<Target Name="RootOutputCopyTarget" AfterTargets="Build">... </ Target>
lorond

44

如果在文本编辑器中编辑.csproj / .vbproj,则可以控制文件在输出目录中的放置位置,以及文件在输出目录中的名称。例如:

<None Include="content\someContent.txt">
  <Link>someContentInOutputDirectory.txt</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

这会将文件content\someContent.txt放入bin\someContentInOutputDirectory.txt。如果需要,还可以在其中选择一个子目录bin。只需将其添加到Link元素。


3
哇,我很幸运现在(而不是两天前)需要这个。谢谢; 这很棒!
Asherah 2014年

2
哦,天哪,谢谢。我只花了6个小时尝试修复一些极端情况下的垃圾,而VS并没有以智能的方式复制.dll。这是对生命,宇宙和万物的真正答案。
布兰登2014年

5
到目前为止,这是最好的解决方案
PhilHdt 2014年

1
我发现这样做并在Visual Studio中重新加载了项目后,依赖关系文件就从解决方案资源管理器中消失了,好像没有包含在项目中一样。但是,它仍然可以按预期进行构建,并且可以根据需要复制到输出。作为解决方法,我当前将每个文件添加两次;一次不执行任何操作,一次设置为“复制到输出”。
Éliette

1
这不是此标记的预期用途。在VS2013中,这会在加载项目时引发警告,并且该文件在添加到项目时不可见,因为它是项目目录。
jpmc26 2016年

15

我相信XCOPY命令可以更好地处理目录和文件。因此,

    XCOPY "$(ProjectDir)common/browserhawk" "$(TargetDir)" /E /I /F /Y

这允许在目标目录之外创建文件夹。

    XCOPY "$(ProjectDir)Templates" "$(TargetDir)" /E /I /F /Y

项目文件夹/文件结构:

    A:\TEMP\CONSOLEAPPLICATION3\TEMPLATES
    ├───NewFolder1
    ├───NewFolder2
    │       TextFile1.txt
    │       TextFile2.txt
    └───NewFolder3
            TextFile1.txt
            TextFile2.txt
            TextFile3.txt

成为:

    A:\TEMP\CONSOLEAPPLICATION3\BIN\DEBUG
    │   ConsoleApplication3.exe
    │   ConsoleApplication3.pdb
    │   ConsoleApplication3.vshost.exe
    │   ConsoleApplication3.vshost.exe.manifest
    ├───NewFolder1
    ├───NewFolder2
    │       TextFile1.txt
    │       TextFile2.txt
    │
    └───NewFolder3
            TextFile1.txt
            TextFile2.txt
            TextFile3.txt

/D可能也很有用,以避免覆盖可能的更改。
KurzedMetal 2015年

10

将以下内容添加到您的.csproj / .vbproj文件中

<Target Name="AfterBuild">
    <Copy
        DestinationFolder="$(OutputPath)"
        SourceFiles="@(RootContent)"
        SkipUnchangedFiles="true"
        />  
</Target>

然后将根文件夹中所需的任何文件的“生成操作”更改为RootContent。


不是通过对话框...而是可以在VS中编辑项目。右键单击项目,然后选择“卸载项目”。然后右键单击并选择编辑。然后,您可以编辑作为项目的MSBuild文件。
保罗·亚历山大

2
谢谢,这看起来很有用。不幸的是,即使将您的代码段添加到.vbproj文件中,RootContent也不会显示在“生成操作”下拉列表中,而手动输入它会导致Visual Studio错误“属性值无效”。我错过了什么?
海因兹

不适用于Visual Studio 2010 C#控制台应用程序项目。
AMissico 2010年

不适用于Visual Studio 2010 VB.NET控制台应用程序项目。
2010年

不适用于Visual Studio 2008 C#控制台应用程序项目。
2010年

5

我在VS2010,VS2015,VS2017和VS2019中使用了此功能。我更喜欢这种解决方案,因为:

  1. XML可在任何项目中重用
  2. 就像任何其他“内容”一样,“ RootContent”被选择为Visual Studio UI中的构建动作。
  3. 就像您期望的那样,遵循“ CopyToOutputDirectory”
  4. RootContent被添加到项目的输出中:通过Project-References进行,遵循“ Clean”等。
  5. 可以使用通配符指定RootContent,以保留递归文件夹结构:
<RootContent Include="common\browserhawk\**">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</RootContent>

在项目文件的开头:

  <ItemGroup>
    <AvailableItemName Include="RootContent">
      <!-- Add "RootContent" as a choice in the "Build Action" dropdown. -->
      <Visible>True</Visible>
    </AvailableItemName>
  </ItemGroup>

从这个答案中借来的

在Microsoft .targets导入之后:

  <PropertyGroup>
    <AssignTargetPathsDependsOn>
      $(AssignTargetPathsDependsOn);
      IncludeRootContentAsContent;
    </AssignTargetPathsDependsOn>
  </PropertyGroup>
  <Target Name="IncludeRootContentAsContent">
    <CreateItem Include="@(RootContent)" AdditionalMetadata="TargetPath=%(RecursiveDir)%(Filename)%(Extension)">
      <Output ItemName="ContentWithTargetPath" TaskParameter="Include" />
    </CreateItem>
  </Target>

从这个答案中借来的


很好-我要换掉RootContent它的意思是“硬编码”,CustomContent以表明这是我们要添加到该项目中的专业内容,我们需要以这种特定方式进行复制。另外,我需要TargetPath=%(RecursiveDir)%(Filename)%(Extension)从指定CustomContent文件到输出路径重新创建文件夹结构。
延诺2015年

@Jonno的目标是将文件直接复制到根输出目录,而不考虑RecursiveDirectory。内置的“内容”构建操作已经为我们提供了一种在维护RecursiveDirectory的同时进行复制的机制。
MattGerg '16

我已经有一段时间没有机会进行测试了,但是是否不会按照OP所说的那样设置“ Content”构建操作导致将文件/common/browserhawk/复制到下面/bin/common/browserhawk/?IIRC,我的意图是进入/common/browserhawk/a.txt/bin/a.txt但允许从那里向下递归,所以/common/browserhawk/secret/stuff.png最终进入/bin/secret/stuff.png
Jonno'2

@Jonno好的,是的,现在完全有意义。我更新了答案以包含%(RecursiveDirectory)。这真的很酷,因为除了在IDE中选择单个文件之外,您还可以使用通配符指定多个文件。使用**通配符时,将保留整个文件夹结构。
MattGerg'2

1
非常感谢您提供如此出色的答案!我认为此答案是正确的答案,原因如下:1.没有外部cmd 2.跨平台
George Anisimov

2

我最终在成功编译后向nant构建文件添加了一个要复制的步骤

<target name="action.copy.browserhawk.config" depends="compile.source">
    <copy todir="${App.Web.dir}/bin/" includeemptydirs="false">
        <fileset basedir="${browserhawk.config.dir}">
            <include name="bhawk_bb.dat" />
            <include name="bhawk_sp.dat" />
            <include name="browserhawk.properties" />
            <include name="maindefs.bdd" />
            <include name="maindefs.bdf" />
            <include name="BH_PRO.lic" />
        </fileset>
    </copy>
    <echo message="COPY BROWSERHAWK CONFIG: SUCCESS   ${datetime::now()}" />
</target>

2
+1,因为对于使用nant的人来说,这仍然是一个有用的答案
克里斯·海恩斯

1

您可以构建一个批处理文件以复制文件并将其作为构建后事件执行。


我最终在一个项目中做到了这一点(尽管我使用的是Python脚本而不是蝙蝠)。
Fire Lancer 2010年
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.