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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

NVITEnd-user supportCommented:
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
Jose Gabriel Ortega CastroCEOCommented:
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
10 Tips to Protect Your Business from Ransomware

Did you know that ransomware is the most widespread, destructive malware in the world today? It accounts for 39% of all security breaches, with ransomware gangsters projected to make $11.5B in profits from online extortion by 2019.

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 CastroCEOCommented:
Ok let me finish my answer with that part.
0
Jose Gabriel Ortega CastroCEOCommented:
[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 CastroCEOCommented:
Ok, let me try the code on my end. I'll answer shortly
0
Jose Gabriel Ortega CastroCEOCommented:
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 CastroCEOCommented:
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
Jose Gabriel Ortega CastroCEOCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Windows Server 2016

From novice to tech pro — start learning today.