8

ビルドをスクリプト化する必要があります。VS.net と統合されているため、MSBUILD を使用しています。ビルド環境から配置フォルダーにいくつかのファイルをコピーしようとしています。MSBuild のコピー タスクを使用しています。しかし、期待どおりにディレクトリツリーをコピーする代わりに。すべてのコンテンツを 1 つのフォルダーにコピーします。ディレクトリツリーのすべてのファイルが1つのフォルダーになることを繰り返します。フォルダーとディレクトリのツリーを宛先フォルダーにコピーするために必要です。足りないものはありますか?

私のビルドスクリプトの関連部分は次のとおりです。

<PropertyGroup>
    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
    <Source>outputfolder</Source>
    <DestEnv>x</DestEnv>
    <DeployPath>\\networkpath\$(DestEnv)</DeployPath>
</PropertyGroup>
<ItemGroup>
    <TargetDir Include="$(DeployPath)\**\*" Exclude="**\web.config"></TargetDir>
    <SourceDir Include="$(Source)\**\*" />
</ItemGroup>    
<Target Name="Clean" >
    <!-- clean detail ... -->
</Target>
<Target Name="migrate" DependsOnTargets="Clean">
    <Copy DestinationFolder="$(DeployPath)" SourceFiles="@(SourceDir)" />
</Target>
4

4 に答える 4

15

コピーに関する MSBuild の問題をデバッグしていたときに見つけた単なる宝石:

http://blog.scrappydog.com/2008/06/subtle-msbuild-bug-feature.html

ItemGroup はターゲットの前に解析されるため、新しいファイルを作成するターゲット (コンパイルなど) は、スクリプトでさらに ItemGroup が参照されたときに取得されません。

Eric Bowen は、この「機能」であるCreateItemタスクの回避策についても説明しています。

<Target Name="Copy" >
    <CreateItem Include="..\Source\**\bin\**\*.exe"
        Exclude="..\Source\**\bin\**\*.vshost.exe">
        <Output TaskParameter="Include" ItemName="CompileOutput" />
    </CreateItem>
    <Copy SourceFiles="@(CompileOutput)" 
        DestinationFolder="$(OutputDirectory)"></Copy>
</Target>

彼に多くの称賛を!

于 2009-01-12T07:53:53.047 に答える
12

コピータスクにDestinationFolderを指定すると、SourceFilesコレクションからすべてのアイテムが取得され、それらがDestinationFolderにコピーされます。ツリー構造を維持するために、コピータスクが各アイテムのパスのどの部分をDestinationFolderに置き換える必要があるかを判断する方法がないため、これは予想されます。たとえば、SourceDirコレクションが次のように定義されている場合:

<ItemGroup>
    <SourceDir Include="$(Source)\**\*" />
    <SourceDir Include="E:\ExternalDependencies\**\*" />
    <SourceDir Include="\\sharedlibraries\gdiplus\*.h" />
</ItemGroup>

宛先フォルダツリーはどのようになると思いますか?

ツリーを保持するには、ID変換を実行し、SourceFilesコレクションのアイテムごとに1つの宛先アイテムを生成する必要があります。次に例を示します。

<Copy SourceFiles="@(Compile)" DestinationFiles="@(Compile->'$(DropPath)%(Identity)')" />

コピータスクは、SourceFilesコレクション内の各アイテムを取得し、ソースアイテム仕様の**の前の部分を$(DropPath)に置き換えることによって、そのパスを変換します。

DestinationFolderプロパティは、次の変換へのショートカットとして記述されている必要があると主張する人もいるかもしれません。

<Copy SourceFiles="@(Compile)" DestinationFiles="@(Compile->'$(DestinationFolder)%(Identity)')" />

残念ながら、それはあなたが避けようとしているフラットフォルダへのディープコピーのシナリオを妨げるでしょうが、他の人々が彼らのビルドプロセスで使用するかもしれません。

于 2008-11-05T23:15:48.207 に答える
5

ディレクトリの内容と構造を再帰的にコピーする非常に単純な例:

<Copy SourceFiles="@(Compile)" DestinationFolder="c:\foocopy\%(Compile.RecursiveDir)"></Copy>

@(Compile) は、コピーするすべてのファイルの ItemGroup です。次のようなものかもしれません:

   <ItemGroup>
      <Compile Include=".\**\*.dll" /> 
   </ItemGroup>

コピー タスクは、xcopy と同様に、すべてのファイルを c:\foocopy にコピーします。

于 2008-11-08T17:36:27.080 に答える
4

私はMSDNの例の1つで例を見つけましたが、理解できませんが、ここにスタックオーバーフローで仲間のトラベラーズの例を残します。上記からの移行ターゲットの修正バージョンは次のとおりです。

<Target Name="migrate" DependsOnTargets="Clean">
    <Copy DestinationFiles="@(SourceDir->'$(DeployPath)\%(RecursiveDir)%(Filename)%(Extension)')" SourceFiles="@(SourceDir)" />
</Target>

誰かが実際にこの例を理解しているなら、説明してください。幸運を!

于 2008-11-05T23:07:26.210 に答える