.
This commit is contained in:
commit
e674d75a20
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
*.exe
|
||||||
|
*.log
|
||||||
|
!snapcontrol.exe
|
||||||
|
|
20
LICENSE.txt
Normal file
20
LICENSE.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2019-2021 Michael H.G. Schmidt
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
104
README.md
Normal file
104
README.md
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# Snapcontrol
|
||||||
|
|
||||||
|
Drive snapshot backup controller.
|
||||||
|
A backup wrapper program for Windows boxes.
|
||||||
|
|
||||||
|
- Starts a backup via Windows Scheduler using Drive Snapshot
|
||||||
|
- Asks the user for permission to start backup
|
||||||
|
- Different backup targets (LOCAL drive, SMB, FTP)
|
||||||
|
- Encryption support (via Drive Snapshot)
|
||||||
|
- Verifies the backup (optional)
|
||||||
|
- Full backup every month
|
||||||
|
- Daily differential backup
|
||||||
|
- Writes detailed logfile and history log
|
||||||
|
- Sends reports via email
|
||||||
|
|
||||||
|
This tool creates an image backups of windows machines, it uses the [Drive Snapshot](http://www.drivesnapshot.de/en/order.htm) tool by Tom Ehlert Software. Please support this great tool and buy a license.
|
||||||
|
|
||||||
|
It is a - so called - wrapper program.
|
||||||
|
|
||||||
|
This is a short description. Detailed documentation follows in the next days.
|
||||||
|
|
||||||
|
## USAGE
|
||||||
|
|
||||||
|
```dos
|
||||||
|
C:\>snapcontrol.exe /?
|
||||||
|
usage: snapcontrol.exe </I | /U | /D | /V>
|
||||||
|
/I = install program and config
|
||||||
|
/U = update scheduler job
|
||||||
|
/D = dry run
|
||||||
|
/V = show version
|
||||||
|
```
|
||||||
|
|
||||||
|
```dos
|
||||||
|
C:\>snapcontrol.exe /V
|
||||||
|
Version = V1.02
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example run
|
||||||
|
|
||||||
|
```dos
|
||||||
|
[2021.05.25 (23:57:07)] ============== starting BACKUP ==============
|
||||||
|
[2021.05.25 (23:57:07)] snapcontrol.exe version = [ V1.02 ]
|
||||||
|
[2021.05.25 (23:57:07)] snapshot.exe version = [ V1.48 ]
|
||||||
|
[2021.05.25 (23:57:07)] OK. Running as Admin ...
|
||||||
|
[2021.05.25 (23:57:07)] INFO: using a NETWORK share for backup ...
|
||||||
|
[2021.05.25 (23:57:07)] INFO: found [ MARS_snapshot_05_ful_C.sna ]
|
||||||
|
[2021.05.25 (23:57:07)] INFO: found [ MARS_snapshot_05_ful_HD1-1.sna ]
|
||||||
|
[2021.05.25 (23:57:07)] INFO: Starting QUICKCHECK for [ MARS_snapshot_05_ful_C.sna ]
|
||||||
|
|
||||||
|
|
||||||
|
23:57:07 Start of Snapshot 1.48.18895 [May 6 2021] at 25.05.2021
|
||||||
|
23:57:07 Running on Windows 10 Professional 64-bit (19042)
|
||||||
|
23:57:07 Memory Info: Total: 7887Mb, Free: 4645Mb, Pagefile total: 9103Mb, Pagefile free: 5835Mb
|
||||||
|
23:57:07 Command line: c:\tools\snapshot64.exe --Logfile:c:\snapshot\backup.log --QuickCheck:\\bar\drive\image\MARS_snapshot_05_ful_C.sna
|
||||||
|
23:57:07 The file structure of \\bar\drive\image\MARS_snapshot_05_ful_C.sna is okay.
|
||||||
|
23:57:07 End of Snapshot 1.48 [May 6 2021] at 25.05.2021
|
||||||
|
[2021.05.25 (23:57:07)] INFO: Starting QUICKCHECK for [ MARS_snapshot_05_ful_HD1-1.sna ]
|
||||||
|
|
||||||
|
|
||||||
|
23:57:07 Start of Snapshot 1.48.18895 [May 6 2021] at 25.05.2021
|
||||||
|
23:57:07 Running on Windows 10 Professional 64-bit (19042)
|
||||||
|
23:57:07 Memory Info: Total: 7887Mb, Free: 4642Mb, Pagefile total: 9103Mb, Pagefile free: 5835Mb
|
||||||
|
23:57:07 Command line: c:\tools\snapshot64.exe --Logfile:c:\snapshot\backup.log --QuickCheck:\\bar\drive\image\MARS_snapshot_05_ful_HD1-1.sna
|
||||||
|
23:57:07 The file structure of \\bar\drive\image\MARS_snapshot_05_ful_HD1-1.sna is okay.
|
||||||
|
23:57:07 End of Snapshot 1.48 [May 6 2021] at 25.05.2021
|
||||||
|
[2021.05.25 (23:57:07)] INFO: executing command [ c:\tools\snapshot64.exe ]
|
||||||
|
[2021.05.25 (23:57:07)] DumpFile: [ \\bar\drive\image\MARS_snapshot_05_$type_$disk.sna ]
|
||||||
|
[2021.05.25 (23:57:07)] HashFile: [ -h\\bar\drive\image\MARS_snapshot_05_$type_$disk.hsh ]
|
||||||
|
[2021.05.25 (23:57:07)] LogFile: [ c:\snapshot\backup.log ]
|
||||||
|
|
||||||
|
|
||||||
|
23:57:08 Start of Snapshot 1.48.18895 [May 6 2021] at 25.05.2021
|
||||||
|
23:57:08 Running on Windows 10 Professional 64-bit (19042)
|
||||||
|
23:57:08 Memory Info: Total: 7887Mb, Free: 4641Mb, Pagefile total: 9103Mb, Pagefile free: 5836Mb
|
||||||
|
23:57:08 Command line: c:\tools\snapshot64.exe --Logfile:c:\snapshot\backup.log -T --EjectDriveAfterBackup --NetUse:\\bar\drive\image,guest,******************** --FullIfHashIsMissing --CreateDir -W -L65536 HD1:* \\bar\drive\image\MARS_snapshot_05_$type_$disk.sna -h\\bar\drive\image\MARS_snapshot_05_$type_$disk.hsh
|
||||||
|
23:57:10 Disks in backup:
|
||||||
|
23:57:10 C: -> \\bar\drive\image\MARS_snapshot_05_dif_C.sna
|
||||||
|
23:57:10 HD1:1 -> \\bar\drive\image\MARS_snapshot_05_dif_HD1-1.sna
|
||||||
|
23:57:10 Preparing for backup
|
||||||
|
23:57:10 Drive HD1:1 is not supported by the Volume Shadow copy service
|
||||||
|
23:57:23 No exchange writer involved, using internal backup engine
|
||||||
|
23:57:24 Start differential backup of C: -> \\bar\drive\image\MARS_snapshot_05_dif_C.sna
|
||||||
|
23:57:24 free space info: total 244.095MB, 199.181MB free, 43.698MB must be saved
|
||||||
|
23:57:24 C: -> \\bar\drive\image\MARS_snapshot_05_dif_C.sna
|
||||||
|
23:59:11 4 sectors need more than 100ms to read
|
||||||
|
23:59:11 C: 44.914MB in use - stored in 26.228KB - 1:47 minutes
|
||||||
|
23:59:11 Success
|
||||||
|
23:59:11 Start verification of: \\bar\drive\image\MARS_snapshot_05_dif_C.sna
|
||||||
|
23:59:12 Success!
|
||||||
|
23:59:12 Start differential backup of HD1:1 -> \\bar\drive\image\MARS_snapshot_05_dif_HD1-1.sna
|
||||||
|
23:59:12 free space info: total 102.396KB, 75.424KB free, 26.972KB must be saved
|
||||||
|
23:59:13 HD1:1 -> \\bar\drive\image\MARS_snapshot_05_dif_HD1-1.sna
|
||||||
|
23:59:13 HD1:1 26.972KB in use - stored in 1.040KB - 0:00 minutes
|
||||||
|
23:59:13 Success
|
||||||
|
23:59:13 Start verification of: \\bar\drive\image\MARS_snapshot_05_dif_HD1-1.sna
|
||||||
|
23:59:13 Success!
|
||||||
|
23:59:13 Snapshot finished successfully
|
||||||
|
23:59:13 End of Snapshot 1.48 [May 6 2021] at 25.05.2021
|
||||||
|
[2021.05.25 (23:59:13)] INFO: END of BACKUP with result SUCCESS !
|
||||||
|
[2021.05.25 (23:59:13)] return=0
|
||||||
|
[2021.05.25 (23:59:13)] INFO: sending mail to: michael@schmidt2.de
|
||||||
|
[2021.05.25 (23:59:13)] INFO: MailServer = smtp.gmail.com
|
||||||
|
[2021.05.25 (23:59:14)] INFO: mail sent
|
||||||
|
```
|
BIN
snapcontrol.exe
Normal file
BIN
snapcontrol.exe
Normal file
Binary file not shown.
112
snapcontrol.ini
Normal file
112
snapcontrol.ini
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
; SNAPCONTROL config file.
|
||||||
|
; https://github.com/mhgschmidt/snapcontrol
|
||||||
|
;
|
||||||
|
; This tool creates an image backups of windows machines,
|
||||||
|
; it uses the Drive Snapshot tool by Tom Ehlert Software.
|
||||||
|
; Please support this great tool and buy a license.
|
||||||
|
; http://www.drivesnapshot.de/en/order.htm
|
||||||
|
;
|
||||||
|
; Copyright (c) 2019-2021 Michael H.G. Schmidt
|
||||||
|
; EMAIL: michael@schmidt2.de
|
||||||
|
; Released under the MIT license.
|
||||||
|
;
|
||||||
|
; IMPORTANT: DO NOT USE quotation marks in this INIFILE !
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
[INSTALL]
|
||||||
|
; where to install the exe and the infile ...
|
||||||
|
InstallTo = c:\snapshot
|
||||||
|
|
||||||
|
; path where snapshot.exe is located ...
|
||||||
|
BinPath = c:\tools
|
||||||
|
|
||||||
|
|
||||||
|
[BACKUP]
|
||||||
|
; target PATH examples:
|
||||||
|
; - "D:\BACKUP" (LOCAL path on drive d:)
|
||||||
|
; - "\\example\share" (SMB share on server "example")
|
||||||
|
; - "/backup" (some path on FTP server)
|
||||||
|
TargetPath = D:\BACKUP
|
||||||
|
|
||||||
|
; active FTP backup with "yes"
|
||||||
|
FtpBackup = no
|
||||||
|
|
||||||
|
; name of ftp server
|
||||||
|
FtpServer = ftp.example.com
|
||||||
|
|
||||||
|
; target USER (only for SMB/FTP mode needed)
|
||||||
|
TargetUser = ftpbackup
|
||||||
|
|
||||||
|
; target PASSWORD (only for SMB/FTP mode needed)
|
||||||
|
TargetPassword = mypassword
|
||||||
|
|
||||||
|
; backup schedule modes:
|
||||||
|
; TIME -> absolute start time (format = hh:mm)
|
||||||
|
; LOGIN -> delay before starting the backup after login (format = mmmm:ss)
|
||||||
|
BackupSched = LOGIN
|
||||||
|
BackupStart = 0005:00
|
||||||
|
|
||||||
|
; disks to dump (please use Drive Snapshot format!)
|
||||||
|
; see http://www.drivesnapshot.de/en/commandline.htm
|
||||||
|
Disks2Dump = HD1:*
|
||||||
|
|
||||||
|
; maximum size of dumpfiles in MB (reduce for fat32 target drives to 4095)
|
||||||
|
DumpSize = 4095
|
||||||
|
|
||||||
|
; verify the backup ?
|
||||||
|
Verify = yes
|
||||||
|
|
||||||
|
; delete all files in the recycle bin before starting the backup ?
|
||||||
|
BurnTrash = no
|
||||||
|
|
||||||
|
; encrypt the backup ?
|
||||||
|
; no: do NOT encrypt
|
||||||
|
; dynamic: generate a password. will be sent via mail
|
||||||
|
; HINT: Generation happens only ONCE and only in case
|
||||||
|
; that "encryptpw" ist empty. snapcontrol will write
|
||||||
|
; the generated password into the inifile !
|
||||||
|
; yes: use the password in variable "encryptpw"
|
||||||
|
Encrypt = no
|
||||||
|
|
||||||
|
; some hard to guess password ---> WRITE IT DOWN !!!
|
||||||
|
; and DO NOT USE quotation marks !
|
||||||
|
EncryptPW =
|
||||||
|
|
||||||
|
; limit write IO in MB/s
|
||||||
|
LimitIO =
|
||||||
|
|
||||||
|
; should drive/media be ejected after backup ? (yes/no)
|
||||||
|
EjectMedia = yes
|
||||||
|
|
||||||
|
|
||||||
|
[LOGGING]
|
||||||
|
LogFile = backup.log
|
||||||
|
HistLog = history.log
|
||||||
|
|
||||||
|
|
||||||
|
[MAIL]
|
||||||
|
;
|
||||||
|
; The mail setup in this config file was tested and works perfectly
|
||||||
|
; for gmail (please be aware that you will have to change your
|
||||||
|
; gmail security settings in case you plan to use gmail)
|
||||||
|
;
|
||||||
|
|
||||||
|
; shall we send a mail ?
|
||||||
|
MailReport = no
|
||||||
|
|
||||||
|
; mail recipient...
|
||||||
|
MailTo = backup@example.com
|
||||||
|
|
||||||
|
; address of SMTP server (TLS/SSL only !)
|
||||||
|
MailServer = smtp.gmail.com
|
||||||
|
|
||||||
|
; port of SMTP server (in most cases it's 465 or 587)
|
||||||
|
MailPort = 465
|
||||||
|
|
||||||
|
; user for sending mail
|
||||||
|
MailUser = example@gmail.com
|
||||||
|
|
||||||
|
; password on mailserver
|
||||||
|
MailPass = mypassword
|
||||||
|
|
540
snapcontrol.pb
Normal file
540
snapcontrol.pb
Normal file
@ -0,0 +1,540 @@
|
|||||||
|
; snapcontrol.pb
|
||||||
|
; https://github.com/mhgschmidt/snapcontrol
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
; Drive snapshot backup controller
|
||||||
|
; - starts backups using drive snapshot
|
||||||
|
; - sends reports via email
|
||||||
|
; LICENSE : MIT License
|
||||||
|
; AUTHOR : Michael H.G. Schmidt
|
||||||
|
; EMAIL : michael@schmidt2.de
|
||||||
|
; DATE : 20210526
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; This tool creates an image backups of windows machines,
|
||||||
|
; it uses the Drive Snapshot tool by Tom Ehlert Software.
|
||||||
|
; Please support this great tool and buy a license.
|
||||||
|
; http://www.drivesnapshot.de/en/order.htm
|
||||||
|
;
|
||||||
|
; Copyright (c) 2019-2021 Michael H.G. Schmidt
|
||||||
|
; Released under the MIT license.
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; INIT (set vars, read args, read inifile etc. pp.)
|
||||||
|
;
|
||||||
|
|
||||||
|
OpenConsole()
|
||||||
|
EnableGraphicalConsole(0)
|
||||||
|
|
||||||
|
Dim filelist$(0)
|
||||||
|
|
||||||
|
Global VERSION$="V1.02"
|
||||||
|
Global installme = 0
|
||||||
|
Global updatesched = 0
|
||||||
|
Global dryrun = 0
|
||||||
|
Global hostname$ = GetEnvironmentVariable("COMPUTERNAME")
|
||||||
|
Global jobname$ = "snapcontrol"
|
||||||
|
Global month$ = FormatDate("%mm", Date())
|
||||||
|
Global day$ = FormatDate("%dd", Date())
|
||||||
|
Global DriveSnapshotVersionOk = 0
|
||||||
|
|
||||||
|
; valid versions for Drive Snapshot we support ...
|
||||||
|
NewList DriveSnapshotVersion$()
|
||||||
|
AddElement(DriveSnapshotVersion$())
|
||||||
|
DriveSnapshotVersion$() = "V1.46"
|
||||||
|
|
||||||
|
AddElement(DriveSnapshotVersion$())
|
||||||
|
DriveSnapshotVersion$() = "V1.47"
|
||||||
|
|
||||||
|
AddElement(DriveSnapshotVersion$())
|
||||||
|
DriveSnapshotVersion$() = "V1.48"
|
||||||
|
|
||||||
|
Procedure Usage()
|
||||||
|
PrintN ("usage: snapcontrol.exe </I | /U | /D | /V>")
|
||||||
|
PrintN (" /I = install program and config")
|
||||||
|
PrintN (" /U = update scheduler job")
|
||||||
|
PrintN (" /D = dry run")
|
||||||
|
PrintN (" /V = show version")
|
||||||
|
End 99
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
; check commandline...
|
||||||
|
If ( CountProgramParameters() >1 )
|
||||||
|
Usage()
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; set path for inifile ...
|
||||||
|
inifile$ = RTrim(GetPathPart(ProgramFilename()),"\") + "\snapcontrol.ini"
|
||||||
|
|
||||||
|
; install job, update job, show version, dry run ...
|
||||||
|
If ( UCase(ProgramParameter(0)) = "/I" )
|
||||||
|
installme = 1
|
||||||
|
ElseIf ( UCase(ProgramParameter(0)) = "/U" )
|
||||||
|
updatesched = 1
|
||||||
|
ElseIf ( UCase(ProgramParameter(0)) = "/V" )
|
||||||
|
PrintN ("Version = " + VERSION$)
|
||||||
|
End 0
|
||||||
|
ElseIf ( UCase(ProgramParameter(0)) = "/D" )
|
||||||
|
dryrun = 1
|
||||||
|
ElseIf ( UCase(ProgramParameter(0)) = "/?" )
|
||||||
|
Usage()
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; Procedure "RunProgram" aborts after writing approx. 8GB data with snapshot64...
|
||||||
|
; so we will use native "system" command...
|
||||||
|
ImportC "msvcrt.lib"
|
||||||
|
system(str.p-ascii)
|
||||||
|
EndImport
|
||||||
|
|
||||||
|
If (Not OpenPreferences(inifile$))
|
||||||
|
PrintN ("FATAL: cannot read inifile [ " + inifile$ + " ] ---> EXIT.")
|
||||||
|
End 98
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
PreferenceGroup("install")
|
||||||
|
Global InstallTo$ = ReadPreferenceString("InstallTo","c:\snapshot")
|
||||||
|
Global BinPath$ = ReadPreferenceString("BinPath","c:\tools")
|
||||||
|
|
||||||
|
PreferenceGroup("backup")
|
||||||
|
Global TargetPath$ = ReadPreferenceString("TargetPath","\\server\share")
|
||||||
|
Global FtpBackup$ = ReadPreferenceString("FtpBackup","no")
|
||||||
|
Global FtpServer$ = ReadPreferenceString("FtpServer","none")
|
||||||
|
Global TargetUser$ = ReadPreferenceString("TargetUser","guest")
|
||||||
|
Global TargetPassword$ = ReadPreferenceString("TargetPassword","guest")
|
||||||
|
Global BackupschedMode$ = ReadPreferenceString("BackupschedMode","LOGIN")
|
||||||
|
Global BackupStart$ = ReadPreferenceString("BackupStart","0005:00")
|
||||||
|
Global Disks2Dump$ = ReadPreferenceString("Disks2Dump","HD1:*")
|
||||||
|
Global DumpSize$ = ReadPreferenceString("DumpSize","4095")
|
||||||
|
Global Verify$ = ReadPreferenceString("Verify","yes")
|
||||||
|
Global BurnTrash$ = ReadPreferenceString("BurnTrash","no")
|
||||||
|
Global Encrypt$ = ReadPreferenceString("Encrypt","no")
|
||||||
|
Global EncryptPW$ = ReadPreferenceString("EncryptPW","")
|
||||||
|
Global LimitIO$ = ReadPreferenceString("LimitIO","")
|
||||||
|
Global EjectMedia$ = ReadPreferenceString("EjectMedia","yes")
|
||||||
|
|
||||||
|
PreferenceGroup("logging")
|
||||||
|
Global LogFile$ = ReadPreferenceString("LogFile","backup.log")
|
||||||
|
Global HistLog$ = ReadPreferenceString("HistLog","history.log")
|
||||||
|
|
||||||
|
; add PATH to logfiles ...
|
||||||
|
LogFile$ = InstallTo$ + "\" + LogFile$
|
||||||
|
HistLog$ = InstallTo$ + "\" + HistLog$
|
||||||
|
|
||||||
|
PreferenceGroup("mail")
|
||||||
|
Global MailReport$ = ReadPreferenceString("MailReport","no")
|
||||||
|
Global MailTo$ = ReadPreferenceString("MailTo","")
|
||||||
|
Global MailServer$ = ReadPreferenceString("MailServer","")
|
||||||
|
Global MailPort = Val(ReadPreferenceString("MailPort",""))
|
||||||
|
Global MailUser$ = ReadPreferenceString("MailUser","")
|
||||||
|
Global MailPass$ = ReadPreferenceString("MailPass","")
|
||||||
|
|
||||||
|
; which Drive Snapshot version should be used ?
|
||||||
|
arch$ = GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
|
||||||
|
If ( arch$ = "x86" )
|
||||||
|
SnapshotBin$ = BinPath$ + "\snapshot.exe"
|
||||||
|
Else
|
||||||
|
SnapshotBin$ = BinPath$ + "\snapshot64.exe"
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; Drive Snapshot found ?
|
||||||
|
If ( FileSize ( SnapshotBin$ ) < 0 )
|
||||||
|
PrintN("ERROR: [ " + SnapshotBin$ + " ] NOT found.")
|
||||||
|
End 1
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; Version check for Drive Snapshot ...
|
||||||
|
DriveSnapshot = RunProgram(SnapshotBin$, "/?", "", #PB_Program_Open | #PB_Program_Read)
|
||||||
|
If DriveSnapshot
|
||||||
|
While ProgramRunning(DriveSnapshot)
|
||||||
|
Out$ = Out$ + ReadProgramString(DriveSnapshot)
|
||||||
|
Wend
|
||||||
|
CloseProgram(DriveSnapshot)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
ForEach DriveSnapshotVersion$()
|
||||||
|
If ( FindString(Out$, DriveSnapshotVersion$()) >0 )
|
||||||
|
DriveSnapshotVersionOk = 1
|
||||||
|
Break
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
|
||||||
|
If ( DriveSnapshotVersionOk = 0 )
|
||||||
|
PrintN("ERROR: Drive Snapshot version is NOT supported!")
|
||||||
|
PrintN(" Supported versions are:")
|
||||||
|
ForEach DriveSnapshotVersion$()
|
||||||
|
PrintN(" - " + DriveSnapshotVersion$())
|
||||||
|
Next
|
||||||
|
End 1
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
;
|
||||||
|
; PROCEDURES
|
||||||
|
;
|
||||||
|
|
||||||
|
Procedure LogMe(Message$)
|
||||||
|
Protected h = OpenFile(#PB_Any, LogFile$,
|
||||||
|
#PB_File_Append | #PB_File_NoBuffering | #PB_Ascii | #PB_File_SharedRead)
|
||||||
|
If h
|
||||||
|
WriteStringN(h, FormatDate("[%yyyy.%mm.%dd (%hh:%ii:%ss)] ", Date()) + Message$)
|
||||||
|
PrintN(FormatDate("[%yyyy.%mm.%dd (%hh:%ii:%ss)] ", Date()) + Message$)
|
||||||
|
CloseFile(h)
|
||||||
|
ProcedureReturn 1
|
||||||
|
EndIf
|
||||||
|
ProcedureReturn 0
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure LogMeRaw(Message$)
|
||||||
|
Protected h = OpenFile(#PB_Any, LogFile$,
|
||||||
|
#PB_File_Append | #PB_File_NoBuffering | #PB_Ascii | #PB_File_SharedRead)
|
||||||
|
If h
|
||||||
|
WriteStringN(h, Message$)
|
||||||
|
PrintN(Message$)
|
||||||
|
CloseFile(h)
|
||||||
|
ProcedureReturn 1
|
||||||
|
EndIf
|
||||||
|
ProcedureReturn 0
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure IsAdmin()
|
||||||
|
ProcedureReturn(system("reg.exe ADD HKLM /F >nul 2>&1"))
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure LogSend(subject$, filename$)
|
||||||
|
InitNetwork()
|
||||||
|
Protected e = 0
|
||||||
|
Protected MailText$ = ""
|
||||||
|
|
||||||
|
If CreateMail(0, "system@" + hostname$ , subject$)
|
||||||
|
AddMailRecipient(0, MailTo$, #PB_Mail_To)
|
||||||
|
LogMe("INFO: MailServer = " + Mailserver$)
|
||||||
|
If ReadFile(0, filename$, #PB_File_SharedRead)
|
||||||
|
While Eof(0) = 0
|
||||||
|
MailText$ + ReadString(0) + Chr($0d) + Chr($0a)
|
||||||
|
Wend
|
||||||
|
CloseFile(0)
|
||||||
|
SetMailBody(0, MailText$)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; send mails ALWAYS with SSL...
|
||||||
|
e = SendMail(0, MailServer$, MailPort, #PB_Mail_UseSSL, MailUser$, MailPass$)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
ProcedureReturn e
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure EndProg(err)
|
||||||
|
Protected s$ = ""
|
||||||
|
|
||||||
|
If ( err = 0 )
|
||||||
|
LogMe("INFO: END of BACKUP with result SUCCESS !")
|
||||||
|
s$ = "BACKUP report - { SUCCESS } @" + hostname$
|
||||||
|
Else
|
||||||
|
LogMe("ERROR: END of BACKUP with result FAILED !")
|
||||||
|
s$ = "BACKUP report - { ERROR ! } @" + hostname$
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; write return code of last command (snapshot.exe) to logfile
|
||||||
|
LogMe("return=" + err)
|
||||||
|
|
||||||
|
; send a report via mail ?
|
||||||
|
If ( LCase(MailReport$) = "yes" )
|
||||||
|
LogMe("INFO: sending mail to: " + MailTo$)
|
||||||
|
If ( LogSend(s$, Logfile$) )
|
||||||
|
LogMe("INFO: mail sent")
|
||||||
|
Else
|
||||||
|
LogMe("FATAL: could not send backup report via email...")
|
||||||
|
LogMeRaw(" please inform your Administrator !")
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; adding actual logfile to histlog...
|
||||||
|
If ReadFile(0, Logfile$, #PB_File_SharedRead)
|
||||||
|
While Eof(0) = 0
|
||||||
|
LogText$ + ReadString(0) + Chr($0d) + Chr($0a)
|
||||||
|
Wend
|
||||||
|
CloseFile(0)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
If OpenFile(0, HistLog$, #PB_File_Append | #PB_File_NoBuffering | #PB_File_SharedRead )
|
||||||
|
FileSeek(0, Lof(0))
|
||||||
|
WriteString(0,LogText$)
|
||||||
|
CloseFile(0)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; remove backup share...
|
||||||
|
dummy = system("net use " + TargetPath$ + " /DELETE >nul 2>&1")
|
||||||
|
|
||||||
|
ClosePreferences()
|
||||||
|
CloseConsole()
|
||||||
|
End err
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure.s mkpass(password_length)
|
||||||
|
chars$ = "abcdef-" ; possible characters, keep these lcase
|
||||||
|
For a = 1 To password_length
|
||||||
|
Select Random(1) ; 0 = char, 1 = digit
|
||||||
|
Case 1 ; is digit
|
||||||
|
pass$ + Str(Random(9))
|
||||||
|
Case 0 ; is character
|
||||||
|
position = Random(Len(chars$)) ; random character selector
|
||||||
|
pass$ + Mid(chars$,position,1)
|
||||||
|
EndSelect
|
||||||
|
Next
|
||||||
|
ProcedureReturn pass$
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; MAIN
|
||||||
|
;
|
||||||
|
|
||||||
|
; installation requested ?
|
||||||
|
If ( installme = 1 )
|
||||||
|
|
||||||
|
; delete old logfiles ...
|
||||||
|
LogMe("INFO: deleting old logfiles ...")
|
||||||
|
dummy = system("del /F /Q " + LogFile$ + " 2>nul")
|
||||||
|
dummy = system("del /F /Q " + HistLog$ + " 2>nul")
|
||||||
|
|
||||||
|
; create directory ...
|
||||||
|
LogMe("INFO: creating directory [ " + InstallTo$ + " ] ...")
|
||||||
|
dummy = system("mkdir " + InstallTo$ + " >nul 2>&1")
|
||||||
|
|
||||||
|
; copy binary and inifile ...
|
||||||
|
LogMe("INFO: copy binary and inifile to folder [ " + InstallTo$ + " ] ...")
|
||||||
|
dummy = system("copy /Y " + inifile$ + " " + InstallTo$ + " 2>nul")
|
||||||
|
dummy = system("copy /Y " + ProgramFilename() + " " + InstallTo$ + " 2>nul")
|
||||||
|
|
||||||
|
; update jobscheduler (selfcall) ...
|
||||||
|
dummy = system(InstallTo$ + "\snapcontrol.exe /U 2>nul")
|
||||||
|
|
||||||
|
ClosePreferences()
|
||||||
|
CloseConsole()
|
||||||
|
End
|
||||||
|
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; update for jobscheduler requested ?
|
||||||
|
If ( updatesched = 1 )
|
||||||
|
username$ = GetEnvironmentVariable("USERNAME")
|
||||||
|
|
||||||
|
; generate call string for task...
|
||||||
|
jobcmd$ = ProgramFilename()
|
||||||
|
|
||||||
|
; check jobtype ...
|
||||||
|
If ( LCase(BackupschedMode$) <> "login" And LCase(BackupschedMode$) <> "time" )
|
||||||
|
PrintN("WARNING: unknown BackupschedMode [ " + BackupschedMode$ + " ] ---> IGNORING. Type will be set to LOGIN.")
|
||||||
|
BackupschedMode$ = "LOGIN"
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; update the job ...
|
||||||
|
PrintN ("Updating windows jobscheduler ...")
|
||||||
|
If ( LCase(BackupschedMode$) = "time" )
|
||||||
|
dummy = system("schtasks /create /F /RL HIGHEST /SC daily /ST " + BackupStart$ + " /TN " + jobname$ + " /TR " + jobcmd$)
|
||||||
|
ElseIf ( LCase(BackupschedMode$) = "login" )
|
||||||
|
dummy = system("schtasks /create /F /RL HIGHEST /SC onlogon /DELAY " + BackupStart$ + " /TN " + jobname$ + " /TR " + jobcmd$)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; show job and print some status messages...
|
||||||
|
dummy = system("schtasks /query /FO List /V /TN " + jobname$)
|
||||||
|
PrintN (Chr(13) + "READY." + Chr(13))
|
||||||
|
|
||||||
|
ClosePreferences()
|
||||||
|
CloseConsole()
|
||||||
|
End
|
||||||
|
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; ASK the user for permission to start ...
|
||||||
|
;
|
||||||
|
|
||||||
|
; FTP backup requested ?
|
||||||
|
If ( FtpBackup$ = "yes" )
|
||||||
|
TargetPath$ = "ftp://" + TargetUser$ + "@" + FtpServer$ + TargetPath$
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
Result = MessageRequester("SnapControl",
|
||||||
|
"Start BACKUP now?" + Chr(13) +
|
||||||
|
"Targetpath => " + TargetPath$,
|
||||||
|
#PB_MessageRequester_YesNo | #PB_MessageRequester_Info)
|
||||||
|
|
||||||
|
If Result = #PB_MessageRequester_No
|
||||||
|
Result = MessageRequester("SnapControl",
|
||||||
|
"backup ABORTED.",
|
||||||
|
#PB_MessageRequester_Ok | #PB_MessageRequester_Warning)
|
||||||
|
CloseConsole()
|
||||||
|
End 0
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
|
||||||
|
; cleanup: delete old Logfile, remove old drive letter...
|
||||||
|
dummy = DeleteFile(LogFile$, #PB_FileSystem_Force)
|
||||||
|
|
||||||
|
LogMe("============== starting BACKUP ==============")
|
||||||
|
LogMe("snapcontrol.exe version = [ " + VERSION$ + " ]")
|
||||||
|
LogMe(" snapshot.exe version = [ " + DriveSnapshotVersion$() + " ]")
|
||||||
|
|
||||||
|
If ( dryrun = 1 )
|
||||||
|
LogMe("DRYRUN - (simulating a backup run) !!!")
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
e = IsAdmin()
|
||||||
|
If ( e = 0 )
|
||||||
|
LogMe("OK. Running as Admin ...")
|
||||||
|
Else
|
||||||
|
PrintN("ERROR: Please run as Administrator !")
|
||||||
|
PrintN(" cannot continue ---> EXIT")
|
||||||
|
End 97
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
;
|
||||||
|
; GENERATE the BACKUP command...
|
||||||
|
;
|
||||||
|
|
||||||
|
; encryption enabled ?
|
||||||
|
If ( LCase(Encrypt$) = "yes" )
|
||||||
|
params$ = "-PW=" + EncryptPW$ + " "
|
||||||
|
If ( EncryptPW$ = "" )
|
||||||
|
LogMe("WARNING: ENCRYPTED backup requested but PASSWORD is not set in infile !")
|
||||||
|
Else
|
||||||
|
LogMe("WARNING: encryption requested. The backup will be encrypted.")
|
||||||
|
LogMeRaw(" --> PLEASE WRITE DOWN YOUR PASSWORD AND STORE IT IN A SAFE PLACE !")
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
If ( LCase(Encrypt$) = "dynamic" )
|
||||||
|
If ( EncryptPW$ = "" )
|
||||||
|
EncryptPW$ = mkpass(20)
|
||||||
|
LogMe("WARNING: ENCRYPTED backup requested and DYNAMIC password was requested !")
|
||||||
|
LogMeRaw(" Generated password is: --->>> " + EncryptPW$ + " <<<---")
|
||||||
|
LogMe("INFO: writing password to inifile...")
|
||||||
|
PreferenceGroup("Global")
|
||||||
|
dummy = WritePreferenceString("EncryptPW", EncryptPW$)
|
||||||
|
Else
|
||||||
|
LogMe("WARNING: ENCRYPTED backup requested. Using DYNAMIC password in inifile !")
|
||||||
|
LogMeRaw(" The password is: --->>> " + EncryptPW$ + " <<<---")
|
||||||
|
EndIf
|
||||||
|
params$ = "-PW=" + EncryptPW$ + " "
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; limit the write rate ?
|
||||||
|
If ( LimitIO$ <> "" )
|
||||||
|
params$ + "--LimitIORate:" + LimitIO$ + " "
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; verify the backup ?
|
||||||
|
If ( LCase(Verify$) = "yes" )
|
||||||
|
params$ + "-T "
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; burn all the trash in the recyclebin ?
|
||||||
|
If ( LCase(BurnTrash$) = "yes" )
|
||||||
|
params$ + "-R "
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; eject media ?
|
||||||
|
If ( EjectMedia$ = "yes" )
|
||||||
|
params$ + "--EjectDriveAfterBackup "
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
|
||||||
|
; FTP backup requested ?
|
||||||
|
If ( FtpBackup$ = "yes" )
|
||||||
|
|
||||||
|
LogMe("INFO: FTP backup, using server [ " + FtpServer$ + " ] for backup ...")
|
||||||
|
|
||||||
|
; add ftp account ...
|
||||||
|
e = system(SnapshotBin$ + " --AddFTPAccount:" + TargetUser$ + "," + FtpServer$ + "," + TargetPassword$)
|
||||||
|
|
||||||
|
; generate filenames for backup ...
|
||||||
|
DumpFile$ = TargetPath$ + "/" + hostname$ + "_snapshot_" + month$ + "_$type_$disk.sna"
|
||||||
|
HashFile$ = "-h" + InstallTo$ + "\" + hostname$ + "_snapshot_" + month$ + "_$type_$disk.hsh"
|
||||||
|
|
||||||
|
Else
|
||||||
|
|
||||||
|
; network share or local drive ?
|
||||||
|
colonpos = FindString(TargetPath$, ":")
|
||||||
|
If ( colonpos = 0 )
|
||||||
|
; no colon found in path this means we are using a network share ...
|
||||||
|
params$ + "--NetUse:" + TargetPath$ + "," + TargetUser$ + "," + TargetPassword$ + " "
|
||||||
|
LogMe("INFO: using a NETWORK share for backup ...")
|
||||||
|
Else
|
||||||
|
; found a ':' at some position means we are using a drive letter ...
|
||||||
|
DRIVE$ = Left(TargetPath$, colonpos)
|
||||||
|
LogMe("INFO: using DRIVE [ " + DRIVE$ + " ] for backup ...")
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; check if there is a full backup file ... in case it was deleted ...
|
||||||
|
If ( FileSize ( TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_ful*.sna" ) < 0 )
|
||||||
|
LogMe("WARNING: no full backup found.")
|
||||||
|
If ( FileSize ( TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_ful*.hsh" ) >= 0 )
|
||||||
|
dummy = system("del /F /Q " + TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_ful*.hsh")
|
||||||
|
LogMe("INFO: [ " + TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_ful*.hsh ] deleted.")
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; check the actual FULL backup file for errors ...
|
||||||
|
; ( must be done BEFORE we run a backup because we don't know - for sure
|
||||||
|
; - wether the last backup was interrupted or not... )
|
||||||
|
i = 1
|
||||||
|
If ExamineDirectory(0, TargetPath$, hostname$ + "_snapshot_" + month$ + "_ful*.sna")
|
||||||
|
While NextDirectoryEntry(0)
|
||||||
|
If DirectoryEntryType(0) = #PB_DirectoryEntry_File
|
||||||
|
ReDim filelist$(i)
|
||||||
|
filelist$(i-1) = DirectoryEntryName(0)
|
||||||
|
LogMe("INFO: found [ " + filelist$(i-1) + " ]")
|
||||||
|
i + 1
|
||||||
|
EndIf
|
||||||
|
Wend
|
||||||
|
FinishDirectory(0)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
e = 0
|
||||||
|
For i = 1 To ArraySize(filelist$())
|
||||||
|
LogMe("INFO: Starting QUICKCHECK for [ " + filelist$(i-1) + " ]")
|
||||||
|
e = system(SnapshotBin$ + " --Logfile:" + LogFile$ + " --QuickCheck:" + TargetPath$ + "\" + filelist$(i-1))
|
||||||
|
If ( e <> 0 )
|
||||||
|
LogMe("ERROR: DELETING last full backup [ REASON: corrupt file! ]")
|
||||||
|
dummy = system("del /F /Q " + TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_ful*.*")
|
||||||
|
Break
|
||||||
|
EndIf
|
||||||
|
Next i
|
||||||
|
|
||||||
|
; generate filenames for backup ...
|
||||||
|
DumpFile$ = TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_$type_$disk.sna"
|
||||||
|
HashFile$ = "-h" + TargetPath$ + "\" + hostname$ + "_snapshot_" + month$ + "_$type_$disk.hsh"
|
||||||
|
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; run BACKUP...
|
||||||
|
;
|
||||||
|
|
||||||
|
; extend params ...
|
||||||
|
params$ + " --FullIfHashIsMissing --CreateDir -W -L" + DumpSize$ + " " + Disks2Dump$
|
||||||
|
|
||||||
|
LogMe("INFO: executing command [ " + SnapshotBin$ + " ]")
|
||||||
|
LogMe(" DumpFile: [ " + DumpFile$ + " ]")
|
||||||
|
LogMe(" HashFile: [ " + HashFile$ + " ]")
|
||||||
|
LogMe(" LogFile: [ " + LogFile$ + " ]")
|
||||||
|
|
||||||
|
If ( dryrun = 0 )
|
||||||
|
e = system(SnapshotBin$ + " --Logfile:" + LogFile$ + " " + params$ + " " + DumpFile$ + " " + HashFile$)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
; end with return code...
|
||||||
|
EndProg(e)
|
||||||
|
|
||||||
|
; IDE Options = PureBasic 5.73 LTS (Windows - x64)
|
||||||
|
; ExecutableFormat = Console
|
||||||
|
; CursorPosition = 58
|
||||||
|
; FirstLine = 20
|
||||||
|
; Folding = --
|
||||||
|
; EnableXP
|
||||||
|
; Executable = snapcontrol.exe
|
||||||
|
; DisableDebugger
|
||||||
|
; Warnings = Display
|
Loading…
Reference in New Issue
Block a user