Created an "empty" Server 2016 domain. How to "fill it" with old server data and retain original last modification date on all folders.

It is time to replace our incredibly simple sbs2003 domain with a virtualized windows server essentials 2016 domain. It is just a file server for a dozen windows 10 clients.  No exchange, sql or other complications.

The new WSEServer  environment uses shadowprotect SPX 6.5.3 for daily backups.

The old sbs2003 used shadowprotect 3, but I believe we could also run SPX 6.4.3 on the old machine which might help solve my problem.

 

We have tested the following:

Step 1 created an "empty" Server04 machine with 10 users and internet connectivity. (\\Server04 is the hypervisor, and \\WSEServer is the virtual fileserver.)

Step 2 use Robocopy to copy old server d:\data\OfficeFolders\ to a USB

Step 3 use robocopy to copy USB to \\WSSERVER\data\OfficeFolders

The test worked very well, except all 10,000 folders now have last date modified as 11/3/2017. Luckily, the file level date is correct so 300,000 files all look fine.

For reasons that are too complicated to explain, losing the folder level dates is a big deal for us. We can live with it, but it will irritate me daily for the next 3 years.

Does anybody have any suggestions?  We tried restoring the SBS 2003 shadow protect 3.0 backups for our restore, but the SIDs caused a bunch of access denied problems.  We tried taking ownership of the USB folders and lower levels, but that step alone ran for about 3 hours. We then tried to restore again, and things went even further downhill.


Does anybody have any ideas?

For instance, if Shadow Protect BACKUP had an option for dropping SIDs that would be great, but I cannot see such an option. Another possibility would be a RESTORE that would automatically drop the SIDS, but that seems even less likely to be possible.
Or possibly a routine that will copy the date mod field and zap the folders after they were restored.  

Maybe powershell to the rescue?

rberke
LVL 5
rberkeConsultantAsked:
Who is Participating?
 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
I've fixed that details and make it public in here:

https://gallery.technet.microsoft.com/scriptcenter/Copy-Files-from-folderA-to-29710ef9

To preserve permissions in USB (needs to be in NTFS) if it's (exFAT or FAT32) you will lose permissions.
0
 
NVITCommented:
With robocopy, use the /dcopy:t switch to keep the original source folder dates
0
 
Dariusz TykaICT Infrastructure Specialist Senior Commented:
Robocopy and the '/dcopy:t' switch will allow you to retain folder datestamp.
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
Well you just need the logic to reset those dates in the files I've prepared a function for you and how to use it.

The only thing you need now is to get the Files recursively

function Set-DateAttributes{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]$OriginalFilePath,
        [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true)]$TargetFilePath
    )
    BEGIN{
        
    }
    PROCESS{
        [System.IO.FileInfo] $fi = New-Object System.IO.FileInfo -ArgumentList $originalFilePAth
        [System.IO.File]::SetCreationTime($targetFilePath,$fi.CreationTime)
        [System.IO.File]::SetLastWriteTime($TargetFilePath,$fi.LastWriteTime)
        [System.IO.File]::SetLastAccessTime( $TargetFilePath,$fi.LastAccessTime)

    }
    END{}
}

Set-DateAttributes -OriginalFilePath "D:\CloudOD\OneDrive\Soporte Curriculum\Taller-Big-Data.pdf" -TargetFilePath "D:\Cloud\Dropbox\Desktop\123\Taller-Big-Data.pdf"

Open in new window


so once you get the files you provide the Source and destination to the function and it will make the threat.
1
 
rberkeConsultantAuthor Commented:
/dcopy is not available on sbs2003.  

Nonetheless, I tested several variations of the following on windows 10.  It created folders with today's date.

robocopy "s:\arobotest" "g:\robousb"  /e /dcopy:t

I have not had time to try the powershell solution yet, mainly because I am very weak in powershell and making it recursive might be tricky.
0
 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
Ok let me finish my answer with that part.
0
 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
[CmdletBinding()]
param(
    [Parameter(Mandatory=$true,Position=0)]$source,
    [Parameter(Mandatory=$true,Position=1)]$target

)

function CopyInfo{
    [CmdletBinding()]
    param(
        [Parameter(Position=0,mandatory=$true)] [string]$sourceDir,
        [Parameter(Position=1,mandatory=$true)] [string]$targetDir
    )

    if(! [System.IO.Directory]::Exists($targetDir) ){
        [System.IO.Directory]::CreateDirectory($targetDir) | Out-Null
    }

    #get source files
    foreach($file in [System.IO.Directory]::GetFiles($sourceDir) ){
            $FilePath=[System.IO.Path]::Combine($targetDir, [System.IO.Path]::GetFileName($file))
            $FileInfoNew      = new-object System.IO.FileInfo($file)

            if(![System.IO.File]::Exists($FilePath) ){
                #Write-Output "Writing $file"
                [System.IO.File]::Copy($file, $FilePath)
                Set-DateAttributes -OriginalFilePath $file -TargetFilePath $FilePath
            }
            else{
				$FileInfoExisting = new-object System.IO.FileInfo($FilePath)
				$FileInfoNew      = new-object System.IO.FileInfo($file)
#setattributes
                Set-DateAttributes -OriginalFilePath $file -TargetFilePath $FilePath
            }
    }

    foreach($dir in [System.IO.Directory]::GetDirectories($sourceDir) ){
    $test = [System.IO.Path]::Combine($targetDir, (New-Object -TypeName System.IO.DirectoryInfo -ArgumentList $dir).Name)
        CopyInfo -sourceDir $dir -targetDir $test
    }
 }

#Copy files from source to target


CopyInfo -sourceDir $Source -targetDir $FolderName 

function Set-DateAttributes{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]$OriginalFilePath,
        [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true)]$TargetFilePath
    )
    BEGIN{
        
    }
    PROCESS{
        [System.IO.FileInfo] $fi = New-Object System.IO.FileInfo -ArgumentList $originalFilePAth
        [System.IO.File]::SetCreationTime($targetFilePath,$fi.CreationTime)
        [System.IO.File]::SetLastWriteTime($TargetFilePath,$fi.LastWriteTime)
        [System.IO.File]::SetLastAccessTime( $TargetFilePath,$fi.LastAccessTime)

    }
    END{}
}

#Set-DateAttributes -OriginalFilePath "D:\CloudOD\OneDrive\Soporte Curriculum\Taller-Big-Data.pdf" -TargetFilePath "D:\Cloud\Dropbox\Desktop\123\Taller-Big-Data.pdf"
CopyInfo -sourceDir $source -targetDir $target

Open in new window


save it as a text file with extension .ps1  (ex: setterDates.ps1)
use:
.\SetterDates.ps1 -source "C:\sources\" -target "D:\Target\Folder"

Must be an elevated windows PowerShell console
0
 
rberkeConsultantAuthor Commented:
I must be doing something wrong. (My powershell skills are practically non-existent and it has been two years since I used it)

I put your program into c:\aatmp\copy.ps1, then used run as administrator to open windows 10 powershell ise (x86)

I then typed the following into command window
 Set-ExecutionPolicy RemoteSigned  
 c:\aatmp\copy.ps1 -source "C:\arobotest\" -target "c:\arobousb"

It started running and created the target directory,
then gave me a bunch of errors. The first one seems to be the most important:  
 

CopyInfo : Cannot bind argument to parameter 'targetDir' because it is an empty string.
At C:\aatmp\copy.ps1:46 char:40
+ CopyInfo -sourceDir $Source -targetDir $FolderName
.                                                                    ============  $foldername was underlined
    + CategoryInfo          : InvalidData: (:) [CopyInfo], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,CopyInf
0
 
rberkeConsultantAuthor Commented:
Actually, I don't think Jose Ortega actually tested his code.

I noticed that $FolderName was never set, so I changed lined 46 to be


CopyInfo -sourceDir $Source -targetDir $Target

That got me a little closer, but the program then aborts with this another messageSet-DateAttributes : The term 'Set-DateAttributes' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\aatmp\copy.ps1:33 char:17
+                 Set-DateAttributes -OriginalFilePath $file -TargetFil ...
+                 ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Set-DateAttributes:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundExceptio


My worry is that I will spend a lot of time debugging the program, only to discover that it will not work.
0
 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
Ok, let me try the code on my end. I'll answer shortly
0
 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
Yeah, It had one unnecessary additional line in the wrong place.

Try this one:
#D:\CloudOD\OneDrive\Soporte Curriculum
#D:\Cloud\Dropbox\Desktop\destTest
[CmdletBinding()]
param(
    [Parameter(Mandatory=$true,Position=0)]$source,
    [Parameter(Mandatory=$true,Position=1)]$target

)

function CopyInfo{
    [CmdletBinding()]
    param(
        [Parameter(Position=0,mandatory=$true)] [string]$sourceDir,
        [Parameter(Position=1,mandatory=$true)] [string]$targetDir
    )

    if(! [System.IO.Directory]::Exists($targetDir) ){
        [System.IO.Directory]::CreateDirectory($targetDir) | Out-Null
    }

    #get source files
    foreach($file in [System.IO.Directory]::GetFiles($sourceDir) ){
            $FilePath=[System.IO.Path]::Combine($targetDir, [System.IO.Path]::GetFileName($file))
            $FileInfoNew      = new-object System.IO.FileInfo($file)

            if(![System.IO.File]::Exists($FilePath) ){
                #Write-Output "Writing $file"
                [System.IO.File]::Copy($file, $FilePath)
                Set-DateAttributes -OriginalFilePath $file -TargetFilePath $FilePath
            }
            else{
				$FileInfoExisting = new-object System.IO.FileInfo($FilePath)
				$FileInfoNew      = new-object System.IO.FileInfo($file)
#setattributes
                Set-DateAttributes -OriginalFilePath $file -TargetFilePath $FilePath
            }
    }

    foreach($dir in [System.IO.Directory]::GetDirectories($sourceDir) ){
    $test = [System.IO.Path]::Combine($targetDir, (New-Object -TypeName System.IO.DirectoryInfo -ArgumentList $dir).Name)
        CopyInfo -sourceDir $dir -targetDir $test
    }
 }

#Copy files from source to target




function Set-DateAttributes{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]$OriginalFilePath,
        [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true)]$TargetFilePath
    )
    BEGIN{
        
    }
    PROCESS{
        [System.IO.FileInfo] $fi = New-Object System.IO.FileInfo -ArgumentList $originalFilePAth
        [System.IO.File]::SetCreationTime($targetFilePath,$fi.CreationTime)
        [System.IO.File]::SetLastWriteTime($TargetFilePath,$fi.LastWriteTime)
        [System.IO.File]::SetLastAccessTime( $TargetFilePath,$fi.LastAccessTime)

    }
    END{}
}

#Set-DateAttributes -OriginalFilePath "D:\CloudOD\OneDrive\Soporte Curriculum\Taller-Big-Data.pdf" -TargetFilePath "D:\Cloud\Dropbox\Desktop\123\Taller-Big-Data.pdf"
CopyInfo -sourceDir $source -targetDir $target

Open in new window

0
 
rberkeConsultantAuthor Commented:
Just as I feared.  The folders copied, but the last modification date is today.  Exactly the same problem that I had with robocopy.

Anybody else have any bright ideas?
0
 
rberkeConsultantAuthor Commented:
If someone can finds vb or powershell code that successfully zaps a folder mod date, I can do the rest of the necessary work.


I am running out of time.  This must be done by Thursday 11/9/2017 or I  will have to live with bad dates for the rest of my career.  The new server goes into production on Friday come hell or high water.

to summarize the problem:

When windows creates a folder, the modification date always shows Today's Date (the date it was created).  That is true if the files are copied with Explorer,  powershell,  robocopy, vba etc.

An unhelpful exception is when explorer drags and MOVES the folders to the SAME DISK. That is internally a rename and the date is untouched. This is unhelpful for me because I must put the files onto the USB.

To override this will require more heroic measures to zap the folder after it created.

For instance, I found code to zap a folder mod date, but, it doesnot work on windows 10, 7 or xp.  (It does work on file dates, just not folder dates)

Sub zapfolder()
               
    Dim objshell, objfolder, objfolderItem
   
    Set objshell = CreateObject("Shell.Application")
    Set objfolder = objshell.Namespace("C:\aatmp\")
    Set objfolderItem = objfolder.Items.Item("d")
    Debug.Print objfolderItem.Name
   
    objfolderItem.ModifyDate = Now() - 5 ' < ========= here is where the zap occurs ===========================
    Debug.Print objfolderItem.ModifyDate
End Sub

If someone can find similar code that successfully zaps a folder mod date, I can do the rest of the necessary work.


I would write a "create_zapdate" program to create a "zapDate" with csv records like this.
1/1/2014 15:00:00, "s:\allFolders\a\b\paul"
5/12/2014 12:33:00, "s:\allfolders\a\b\mary"
another time stamp,"s:\allfolders\a\b"

I would also write a "Apply_zapdate" program that uses the csv  to zap the USB disk.
0
 
rberkeConsultantAuthor Commented:
add xcopy to the list.  Folders lose date/time for xcopy, robocopy, explorer, powershell, and many vba techniques. (there may be some that work, but I have not been able to find them)

rberke
0
 
Jose Gabriel Ortega CCEO Faru Bonon ITCommented:
So I modify the files within the folders. do you want that to work with the folders as well?
I didn't know that I thought it was enough with the files.
Will add the folders.
0
 
rberkeConsultantAuthor Commented:
ABSOLUTLY I want the folders.  In my first post I said "Luckily, the file level date is correct so 300,000 files all look fine."

The folders are the big problem, and I would be incredibly grateful if you can solve it.

But, please test it by going TO a USB.

This is because copies to USB drives are asymmetrical:
     Going from a server to USB resets all dates to Now().  
     Going from USB to a server retains the USB's folder dates.
0
 
rberkeConsultantAuthor Commented:
Hot dog it almost works !!!!   I set-executionpolicy unrestricted then ran a very smple tests that worked great.

But a slightly more complicated test had errors.  The errors cannot be too significant because the resulting folders looks exactly right, 9 files in two folders with the correct date stamp on both folders.

By the way, your public website shows you have tested on 6 versions of window INCLUDING Server 2003 !!!  That is really impressive.

Anyway, here are the first few errors:

PS C:\WINDOWS\system32>  c:\aatmp\CopyNsetDates.ps1 -source "s:\arobotest\" -target "g:\arobousb"

Writing "g:\arobousb\Thumbs.db"
The Creation,LastWrite and LastAccess times were set on the file s:\arobotest\Thumbs.db
Set-Acl : AclObject
At C:\aatmp\CopyNsetDates.ps1:184 char:9
+         Set-Acl $TargetFilePath $OriginalFilePath
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (s:\arobotest\Thumbs.db:String) [Set-Acl], ArgumentException
    + FullyQualifiedErrorId : SetAcl_AclObject,Microsoft.PowerShell.Commands.SetAclCommand
 
Writing "g:\arobousb\~$cro Instructions Template.doc"
The Creation,LastWrite and LastAccess times were set on the file s:\arobotest\~$cro Instructions Template.doc
Set-Acl : AclObject
At C:\aatmp\CopyNsetDates.ps1:184 char:9
+         Set-Acl $TargetFilePath $OriginalFilePath
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (s:\arobotest\~$...ns Template.doc:String) [Set-Acl], ArgumentException
    + FullyQualifiedErrorId : SetAcl_AclObject,Microsoft.PowerShell.Commands.SetAclCommand
 
Writing "g:\arobousb\future templates\do not use yet FCC Form 500 instructions.doc"
The Creation,LastWrite and LastAccess times were set on the file s:\arobotest\future templates\do not use yet FCC Form 500 i
nstructions.doc
Set-Acl : AclObject
At C:\aatmp\CopyNsetDates.ps1:184 char:9
+         Set-Acl $TargetFilePath $OriginalFilePath
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (s:\arobotest\fu...nstructions.doc:String) [Set-Acl], ArgumentException
    + FullyQualifiedErrorId : SetAcl_AclObject,Microsoft.PowerShell.Commands.SetAclCommand
 
Writing "g:\arobousb\future templates\do not use yet FCC Form 500 with &.dot"
The Creation,LastWrite and LastAccess times were set on the file s:\arobotest\future templates\do not use yet FCC Form 500 w
ith &.dot
Set-Acl : AclObject
At C:\aatmp\CopyNsetDates.ps1:184 char:9
+         Set-Acl $TargetFilePath $OriginalFilePath
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (s:\arobotest\fu... 500 with &.dot:String) [Set-Acl], ArgumentException
    + FullyQualifiedErrorId : SetAcl_AclObject,Microsoft.PowerShell.Commands.SetAclCommand
0
 
rberkeConsultantAuthor Commented:
Thanks for your help
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.