My understanding is that when a Win 9x/Me system is logging on to an NT that there is not an easy way to copy all
changed files from a user's hard drive area to a backup area on the network.
In short, there is no effective
update program. XCOPY comes close but does not do a Update the way the original XCOPY from 3-Com did, 1983.
If this is incorrect, please let me know and I'll ask to take this FAQ down, but the question does seem to arrive on the NT4.0 server forum regularly.
The material below lets you put a few lines into a Logon Script to move only and all the
altered and
new files from, e.g. C:\My Documents on the users hard drive to an area on the net, e.g. N:\users\sarah\backup\mydocs
The procedure is to:
[ul][li]List the files to be considered into a file. e.g.
Code:
DIR "C:\my documents\*.*" /s/b/a-d > filelist.dat
Notes: 1. the /a-d eliminates listing subdirectories. 2. Quotes are not needed but for paths with spaces in the path name.
[li]Run Update naming the file and the target area
Code:
Update filelist.dat N:\users\sarah\backup\mydocs
[/ul]
Update will consider each of the files and only move new ones or ones whose size, time, or date has changed, Last Modify time.
UpDate creates a log, appended to, of events, Update.log in the current directory. Therefore a snip from a logon script might look like:
Example:
Code:
Del update.log
DIR "c:\my documents" /s/b/a-d> files.dat
Update files.dat N:\users\%username%\backup
In testing it checks about 200 files per second, of course longer for moving files that need to be updated.
The source is attached in VB 5.0, if one needs and EXE contact me, but you will need MSVBVM50.EXE from MS.
j@roninsoftwaregroup.com
p.s. Of course I would like feedback for whether it works or not on various platforms. I'm unwillingly at leisure and do not have too many NT/2K servers at home to test with.
p.p.s. I could do it in C/++ but that would be a product and I'd have to charge $20 for it. Could get rid of that clunky DIR step, though.
p
3.s. For you advanced weekies like myself: The code below does not use the API FindFileFirst... which would solve the problems with DIR not being recursive and eliminate DIR the step in Batch because I wanted the code to be sufficiently short and readable for people to try it in their VB. They can learn about API calls later.
p
4.s. I favor the explicit variable and small routine size convetnions (Mills & Dykstra,
Structered Methodologies, 1967) which eliminates much of the need for explicit casting the whole module, and is much more readable. All those DIM statements are dim in an otherwise fifteen line module. 2 cents.
--------------------------------------------------------------------
Code:
Attribute VB_Name = "Update"
DefLng A-Z
Declare Function GetTickCount Lib "kernel32" () As Long
Sub Main()
' (c) James Nickson, Ronin Software Group.
' May be copied freely if ENTIRELY un-modified.
' send bugs to j@roninsg.com
' DIR in VBasic is NOT recursive so we need a list of source
' areas to copy from.
' Instructions for a run suppose we were backing up
' c:\mydocs , all the files
' to N:\USERS\jnicks\mydocs
' DIR c:\mydocs /A-D/S/B > copyfils to create a file list.
' UPDATE copyfils "N:\USERS\jnicks\mydocs"
' UPDATE copies NEW files or ones whose size or date has changed.
' as in DIR "c:\my documents" /a-d/s/b > update.dat
' then run Update update.dat \\bakserver\usres\backup\michael
' Damn MS for not being able to save DIR context! The ratfinks.
a$ = Trim$(Command$)
'MsgBox "debug"
'a$ = "update.dir " + App.Path + "\test"
split Trim$(a$), filelist$, toptarget$
target$ = toptarget$
makalldir target$
Open "update.log" For Append As #99
Print #99, vbCrLf; "Update to " + target$, Time$, Date$
tstart = GetTickCount()
Open filelist$ For Input As #1
Do While Not EOF(1)
Line Input #1, nowfile$
GoSub doafile
Loop
Print #99, "Elapsed: " _
; Format$((GetTickCount() - tstart) / 1000#, "Standard") _
; " secs."
Close
End
' duh, that was easy.
doafile:
splitpath nowfile$, fromdir$, fil$
If firsttime = 0 Then firsttime = 1: _
strtpathlen = Len(fromdir$)
relpath$ = Mid$(fromdir$, strtpathlen + 1)
If Len(relpath$) Then _
nowtarg$ = oneback$(target$ + "\" + relpath$): _
makalldir (nowtarg$) _
Else nowtarg$ = target$
targetfil$ = oneback$(nowtarg$ + "\" + fil$)
copyifnew nowfile$, targetfil$
Return
End Sub
Sub copyifnew(srcfile$, targfile$)
' check to see if file there, while we are there clear attributes.
On Local Error GoTo nofile
tattr = GetAttr(targfile$)
'An error flag is thrown if there is no target file, COPY it.
If errsw Then
errsw = 0
FileCopy srcfile$, targfile$
If errsw Then
Print #99, "BUSY, locked, wrong privileges "; srcfile$; " or "; targfile$
Else
Print #99, "Created "; targfile$; " from "; srcfile$
End If
Exit Sub
End If
If tattr And 7 Then SetAttr targfile$, 0
On Local Error GoTo 0
' File is there and attributes cleared, check timedate and lens
If FileDateTime(targfile$) <> FileDateTime(srcfile$) Or _
FileLen(targfile$) <> FileLen(srcfile$) _
Then _
FileCopy srcfile$, targfile$: _
Print #99, "Updating "; srcfile; " to "; targfile$
Exit Sub
nofile: errsw = -1: Resume Next
End Sub
Sub splitpath(a$, p$, m$)
' split into path and mask or file names.
alen = Len(a$)
If alen = 0 Then p$ = "": m$ = "": Exit Sub
For i = alen To 1 Step -1
If "\" = Mid$(a$, i, 1) Then Exit For
Next
Select Case i
Case Is >= alen, 0: errout ("Bad Splitpath: " + a$): End
Case Else:
p$ = Mid$(a$, 1, i - 1)
m$ = Mid$(a$, i + 1)
End Select
End Sub
Sub split(a$, l$, r$)
j = InStr(a$, " ")
Select Case j
Case 0: l$ = a$: r$ = ""
Case Else:
l$ = Trim$(Mid$(a$, 1, j - 1))
r$ = Trim$(Mid$(a$, j + 1))
End Select
End Sub
Sub errout(a$)
Open "Update.err" For Output As #1
Print #1, a$
Close: End
End Sub
Function oneback$(a$)
b$ = a$ + " "
j = InStr(b$, "\\")
Do While j
b$ = Mid$(b$, 1, j) + Mid$(b$, j + 2)
j = InStr(b$, "\\")
Loop
oneback$ = Trim$(b$)
End Function
Sub makalldir(a$)
Static lastone$
If a$ = lastone$ Then Exit Sub
lastone$ = a$
On Local Error Resume Next
js = 1
j = InStr(js, a$, "\")
Do While j
js = j + 1
nowp$ = Left(a$, j - 1)
MkDir nowp$
j = InStr(js, a$, "\")
Loop
MkDir a$
On Local Error GoTo 0
End Sub