12

I'm currently using an msbuild file to copy some files to the public documents folder when my EXE is compiled. My current script includes this:

<Target Name="DeployToPublicDocuments"
              Inputs="@(DeploymentItems)"
              Outputs="$(PublicDocumentsFolder)%(Path)\%(DeploymentItems.RecursiveDir)%(DeploymentItems.Filename)%(DeploymentItems.Extension)">
        <Copy SourceFiles="%(DeploymentItems.FullPath)"
            DestinationFiles="$(PublicDocumentsFolder)%(Path)\%(DeploymentItems.RecursiveDir)%(DeploymentItems.Filename)%(DeploymentItems.Extension)"
                Condition="!Exists('$(PublicDocumentsFolder)%(Path)\%(DeploymentItems.RecursiveDir)%(DeploymentItems.Filename)%(DeploymentItems.Extension)')" />

This code only copies if the destination doesn't exist. However, I want to replace the destination if my source is newer. How do I modify my script to make that happen? I see the SkipUnchangedFiles flag, but it also compares file size to determine if the destination should be overwritten. That is not what I want.

Brannon
  • 5,324
  • 4
  • 35
  • 83
  • How are you determining when it is newer? The reason I ask is because if someone modifies the destination by hand, the destination is now newer based on modified time. The only other time to use is created time and that would only work if you delete the source before creating it. – Matt Slagle Nov 04 '13 at 16:39
  • I'm using the Modification Date for determining what is newer. As long as the destination is newer than the source, I don't want to overwrite it. – Brannon Nov 04 '13 at 17:20

2 Answers2

18

Your copy's conditional can be changed as follows:

    <Copy SourceFiles="%(DeploymentItems.FullPath)"
        DestinationFiles="$(PublicDocumentsFolder)%(Path)\%(RecursiveDir)%(Filename)%(DeploymentItems.Extension)"
            Condition="%(Filename)!='' AND (!Exists('$(PublicDocumentsFolder)%(Path)\%(RecursiveDir)%(Filename)%(DeploymentItems.Extension)') OR $([System.DateTime]::Parse('%(ModifiedTime)').Ticks) &gt; $([System.IO.File]::GetLastWriteTime('$(PublicDocumentsFolder)%(Path)\%(RecursiveDir)%(Filename)%(DeploymentItems.Extension)').Ticks))" />

%(ModifiedTime) = Modified Datetime of the source file

$([System.IO.File]::GetLastWriteTime($(PublicDocumentsFolder)%(Path)\%(RecursiveDir)%(Filename)%(DeploymentItems.Extension))) = Modified Datetime of the destination file, if it exists

Let me know if this works or not, did not test.

blaz
  • 314
  • 4
  • 9
Matt Slagle
  • 1,075
  • 9
  • 19
  • 1
    I ran your code and got this: A numeric comparison was attempted on "%(ModifiedTime)" that evaluates to "2013-05-22 15:53:21.5210339" instead of a number – Brannon Nov 04 '13 at 21:47
  • 2
    It looks like I got it working with this enhancement: `$([System.DateTime]::Parse('%(ModifiedTime)').Ticks)` – Brannon Nov 04 '13 at 23:20
  • One more minor edit: you need to specify `.Ticks` on the end of the second DateTime clause as well. – Brannon Nov 05 '13 at 15:59
9

I think you may have misread the docs:

SkipUnchangedFiles

If true, skips the copying of files that are unchanged between the source and destination. The Copy task considers files to be unchanged if they have the same size and the same last modified time.

http://msdn.microsoft.com/en-us/library/vstudio/3e54c37h.aspx

Community
  • 1
  • 1
Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
  • 3
    So if someone modifies a destination file by hand, I don't want that file overwritten until the source is newer than it. SkipUnchangedFiles doesn't achieve that, true? – Brannon Nov 04 '13 at 16:20
  • @Brannon I think I may have misread your question! Understand what you want now. Perfectly reasonable, but I don't know how to do it. – Colonel Panic Nov 05 '13 at 14:26