Kawvin批处理备份(FreeFileSync)V6.1.5

使用AHK写的外壳,主要是为了配合FreeFileSync快速实现多方案的备份的

1、可以设置多个备份计划,每个备份计划里可以设置多个备份项

2、使用XML作为配置文件,避免FreeFileSync每一个备份项都要单独一个文件的问题

3、F1-F8切换到列表1-8项

4、可以备份完自动关机,放那里直接去睡觉就OK啦……

好用,谁用谁知道,哇哈哈哈哈!!!

Kawvin批处理备份(FreeFileSync)V6.1.5

↓↓↓↓↓↓↓↓↓↓↓↓↓下面是源码↓↓↓↓↓↓↓↓↓↓↓↓↓

/*
    程序: Kawvin批处理备份(FreeFileSync)
    作用: 使用FreeFileSync批量备份文件
    作者: Kawvin
    版本: 6.1.5_2018.12.31
    使用方法:
    6.1.5更新说明:增加compare比较文件夹功能
*/

Label_Init: ;{脚本前设置
#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
;}

Label_DefVar:   ;{变量定义
	global MyAppVer:="Kawvin批处理备份(FreeFileSync)V6.1.5"
    global BackupXML:=A_ScriptDir . "\KawvinBatchBackup.xml"
	global Timeout:=									;倒计时时间
    global ProjectArray:={}		;用来进行保存所有的备份计划
    global Project_List:=
    global Item_List:=
    ReadXMLToArray(BackupXML)
;}

Label_DrawGUI:  ;{绘制窗体
    Menu Tray, Icon, shell32.dll, 47
    ;~ Gui New,+AlwaysOnTop
    Gui Add, GroupBox, x5 y3 w860 h40, 【1】设置
    Gui Add, Text, x15 y15 w151 h23 +0x200, FreeFileSync主程序路径:
    Gui Add, Edit, x160 y15 w650 h21  vAppPath,%AppPath%
    Gui Add, Button, x815 y14 w40 h23 g程序路径浏览, 浏览
    
    Gui Font, Bold c0x0000FF
    Gui Add, GroupBox, x5 y50 w320 h360, 【2】备份计划  【列表右键有惊喜】
    Gui Font
    Gui Add, Text, x15 y70 w55 h23 +0x200 , 备份计划:
    Gui Add, DropDownList, x80 y71 w234 vProject_Sel g备份计划_变动, %Project_List%
    Gui Add, Text, x15 y96 w55 h23 +0x200, 备份项目:
    Gui Font, Bold c0xFF0000
    Gui Add, Text, x100 y96 w200 h23 +0x200 vLastBackTime, 最近备份:
    Gui Font
    Gui Add, ListBox, x15 y122 w300 h280 vItem_Sel g备份项目_变动, %Item_List%

    Gui Add, GroupBox, x330 y50 w535 h112, 【2.1】项目信息
    Gui Add, Text, x340 y69 w60 h22 +0x200, 项目名称:
    Gui Add, Edit, x405 y70 w450 h21 vItemName
    Gui Add, Text, x340 y99 w60 h22 +0x200, 源文件夹:
    Gui Add, Edit, x405 y100 w405 h21 vSourceDir
    Gui Add, Button, x815 y99 w40 h23 g源文件夹浏览, 浏览
    Gui Add, Text, x340 y129 w60 h23 +0x200, 目标目录:
    Gui Add, Edit, x405 y130 w405 h21 vDirectionDir
    Gui Add, Button, x815 y129 w40 h23 g目标目录浏览, 浏览

    Gui Add, GroupBox, x330 y165 w320 h170, 【2.2】备份选项
    Gui Add, Text, x340 y189 w57 h20 +0x200, 比较内容:
    Gui Add, DropDownList, x415 y190 w220 vCompare, 文件时间和大小||文件内容|文件大小
    Gui Add, Text, x340 y219 w57 h20 +0x200, 备份方式:
    Gui Add, DropDownList, x415 y220 w220 vSynchronize, 双向  <->||镜像  ->|更新  >
    Gui Add, Text, x338 y250 w72 h20 +0x200, 进度对话框:
    Gui Add, CheckBox, x415 y250 w80 h23 vProgressDialogMinimized, 最小化运行
    Gui Add, CheckBox, x515 y250 w70 h23 vProgressDialogAutoClose, 自动关闭
    Gui Add, Text, x340 y280 w57 h20 +0x200, 错误处理:
    Gui Add, CheckBox, x415 y280 w71 h23 vErrorsIgnore, 忽略错误
    Gui Add, DropDownList, x515 y280 w120 vErrorDialog, 弹出对话框|取消备份
    Gui Add, Text, x340 y309 w72 h20 +0x200, 完成后操作:
    Gui Add, DropDownList, x415 y310 w220 vPostSyncAction, |系统休眠|系统关机

    Gui Add, GroupBox, x330 y340 w320 h70, 【3】操作
    Gui Add, Button, x380 y360 w100 h40 Default g一键备份, 一键备份
    Gui Font, Bold c0x0000FF
    Gui Add, CheckBox, x520 y370 w95 h23 vShutdownAfterfinish, &A 完成关机
    Gui Font
    
    Gui Add, GroupBox, x655 y165 w210 h70, 【4】备份计划
    Gui Add, Button, x670 y190 w85 h30 g新建计划, 4.1新建计划
    Gui Add, Button, x765 y190 w85 h30 g删除计划, 4.2删除计划

    Gui Add, GroupBox, x655 y255 w210 h70, 【5】备份项目
    Gui Add, Button, x670 y280 w85 h30 g单个添加, 5.1单个添加
    Gui Add, CheckBox, x765 y280 w90 h30 vAuto, 自动批量添加

    Gui Add, GroupBox, x655 y340 w210 h70, 【6】保存
    Gui Add, Button, x670 y365 w85 h30 g确认修改, 确认修改
    Gui Add, Button, x765 y365 w85 h30 g保存到XML, 保存到XML
    
    ;~ Gui Add, Progress, x190 y420 w500 h23 -Smooth  vProgress1, 0
    Gui Add, Progress, x190 y420 w500 h23 -Smooth Hidden vProgress1, 0
    Gui Font, c0xFF0000
    Gui Add, Text, x15 y420 w40 h19 +0x200, 说明:
    Gui Add, Text, x15 y445 w850 h19 +0x200, 一、①在【2.1】、【2.2】录入相关信息后;②使用【5.1单个添加】
    Gui Add, Text, x15 y470 w850 h19 +0x200, 二、不勾选【自动批量添加】,①按住Ctrl,拖动【单个】目标目录到本窗体;②拖动【单个】源文件夹到本窗体;③录入项目名称后;④使用【5.1单个添加】
    Gui Add, Text, x15 y495 w850 h19 +0x200, 三、勾选【自动批量添加】,①按住Ctrl,拖动【单个】目标目录到本窗体;②拖动【多个】源文件夹到本窗体;③逐个确认项目名称后自动添加
    Gui Add, Text, x15 y520 w850 h19 +0x200, 四、①拖动【单个】FreeFileSync文件到本窗体,自动添加到项目列表;②拖动【多个】FreeFileSync文件到本窗体,③逐个确认输入项目名称后自动添加
    Gui Font, s12 Bold
    Gui Add, Text, x15 y545 w850 h25 +0x200, 五、保存:①修改已有项目,需【确认修改】;②【确认修改】或【单个添加】或【批量添加】后须【保存到XML】
    Gui Font
    Gui Add, Edit, x400 y490 w240 h21 vUUID Disabled Hidden
    gosub,窗体初始化
    GuiControl,choose,Project_Sel,1
    gosub,备份计划_变动
    Gui Show, w880 h580, %MyAppVer%
Return
;}

GuiEscape:  ;{
GuiClose:
    ExitApp
return
;}

F1::Guicontrol,Choose,Project_Sel,1   ;{ F1-F8切换到列表1-8项
F2::Guicontrol,Choose,Project_Sel,2
F3::Guicontrol,Choose,Project_Sel,3
F4::Guicontrol,Choose,Project_Sel,4
F5::Guicontrol,Choose,Project_Sel,5
F6::Guicontrol,Choose,Project_Sel,6
F7::Guicontrol,Choose,Project_Sel,7
F8::Guicontrol,Choose,Project_Sel,8
;}

程序路径浏览:  ;{
    FileSelectFile, AppPath, 3, , 请设定FreeFileSync程序路径, 程序 (*.exe)
	if (AppPath !="")
		Guicontrol,,AppPath,%AppPath%
return
;}

源文件夹浏览:  ;{
    ;选择目录
	FileSelectFolder, SourceDir, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, 3,选择目录
	if (SourceDir !="")
		Guicontrol,,SourceDir,%SourceDir%
return
;}

目标目录浏览:  ;{
    ;选择目录
	FileSelectFolder, DirectionDir, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, 3,选择目录
	if (DirectionDir !="")
		Guicontrol,,DirectionDir,%DirectionDir%
return
;}

新建计划:   ;{
    InputBox,MyTemInput,请输入备份计划名称,,,250,100
    if (MyTemInput="")
        return
    if (instr(Project_List,MyTemInput)) {
        MsgBox, 0, 提示, 该名称已存在,请重新输入
        return
    }
    Project_List.= "|" MyTemInput
    GuiControl,,Project_Sel,%MyTemInput%
    Guicontrol,ChooseString,Project_Sel,%MyTemInput%
    gosub,备份计划_变动
return
;}

删除计划:   ;{
    GuiControlGet,Project_Sel,,Project_Sel
    MsgBox, 36, 提示, 确认删除【%Project_Sel%】备份计划及备份项目?
    IfMsgBox,yes
    {
        loop,% ProjectArray.length()
        {
            aProject:=ProjectArray[A_index]
            if (aProject.Name=Project_Sel) {
                ProjectArray.removeat(A_index)
                break
            }
        }
        if regexmatch(Project_List, "(\|)" . Project_Sel . "(\|)")
            Project_List:=RegExReplace(Project_List,"(\|)" . Project_Sel,"") 
        if regexmatch(Project_List, "^" . Project_Sel .  "(\|)")
            Project_List:=RegExReplace(Project_List,Project_Sel  .  "(\|)","") 
        if regexmatch(Project_List, "(\|)" . Project_Sel . "$")
            Project_List:=RegExReplace(Project_List,"(\|)" . Project_Sel,"") 
        GuiControl,,Project_Sel,|
        GuiControl,,Project_Sel,%Project_List%
        Guicontrol,Choose,Project_Sel,1
        gosub,备份计划_变动
    }
return
;}

单个添加:   ;{
    aUUID:=UUIDCreate()
    GuiControlGet,aProject_Sel,,Project_Sel
    GuiControlGet,aItemName,,ItemName
    GuiControlGet,aCompare,,Compare
    GuiControlGet,aSynchronize,,Synchronize
    GuiControlGet,aSourceDir,,SourceDir
    GuiControlGet,aDirectionDir,,DirectionDir
    GuiControlGet,aErrorsIgnore,,ErrorsIgnore
    GuiControlGet,aProgressDialogMinimized,,ProgressDialogMinimized
    GuiControlGet,aProgressDialogAutoClose,,ProgressDialogAutoClose
    GuiControlGet,aErrorDialog,,ErrorDialog
    GuiControlGet,aPostSyncAction,,PostSyncAction
    if(aItemName="" or aSourceDir="" or aDirectionDir="") {
        MsgBox, 0, 提示, 【项目名称】或【源文件夹】或【目标目录】为空,请重新输入
        return
    }
    if (aCompare="文件时间和大小")
        aCompare:="TimeAndSize"
    else if (aCompare="文件内容")
        aCompare:="Content"
    else if (aCompare="文件大小")
        aCompare:="Size"
    if (aSynchronize="双向  <->")
        aSynchronize:="TwoWay"
    else if (aSynchronize="镜像  ->")
        aSynchronize:="Mirror"
    else if (aSynchronize="更新  >")
        aSynchronize:="Update"
    if (aErrorDialog="取消备份")
        aErrorDialog:="Cancel"
    else
        aErrorDialog:="Show"
    if (aPostSyncAction="系统休眠")
        aPostSyncAction:="Sleep"
    else if (aPostSyncAction="系统关机")
        aPostSyncAction:="Shutdown"
    else 
        aPostSyncAction:="None"
    aErrorsIgnore:=cBool(aErrorsIgnore)
    aProgressDialogMinimized:=cBool(aProgressDialogMinimized)
    aProgressDialogAutoClose:=cBool(aProgressDialogAutoClose)
    aBackupItem:=new BackupItem(aUUID,aItemName,aCompare,aSynchronize,aSourceDir,aDirectionDir,aErrorsIgnore,aProgressDialogMinimized,aProgressDialogAutoClose,aErrorDialog,aPostSyncAction)
    HasProject:=0
    loop,% ProjectArray.length()
    {
        if (ProjectArray[A_index].Name=aProject_Sel){
            ProjectArray[A_index].Items.push(aBackupItem)
            HasProject:=1
            break
        }
    }
    if (!HasProject) {
        Project:={}
        Project.Items:={}
        Project.Name:=aProject_Sel
        Project.LastBuckupTime:=""
        Project.Items.push(aBackupItem)
        ProjectArray.push(Project)
    }
    Item_List.= "|" aItemName
    GuiControl,,Item_Sel,|
    GuiControl,,Item_Sel,%Item_List%
    GuiControl,ChooseString,Item_Sel,%aItemName%
return
;}

GuiDropFiles:   ;{拖拽文件到窗体
    GuiControlGet,aProject_Sel,,Project_Sel
    if (aProject_Sel=""){
        MsgBox, 0, 提示, 请先创建备份计划!
        return
    }
    MySel:=A_GuiEvent
    ;【1】判断是单文件还是多文件
    if (instr(MySel,"`n")){ ;多文件
        Loop,parse,MySel,`n,`r
        {
            if (A_LoopField="")
                continue
            If InStr(FileExist(A_LoopField), "D") { ;区分是否文件夹,Attrib= D ,则是文件夹
                
                GuiControlGet,DirectionDir,,DirectionDir
                if (DirectionDir=""){
                    MsgBox, 48, 提示, 请先选择【目标目录】
                    return
                }
                aDirName:=substr(A_LoopField,instr(A_LoopField,"\",,0,1)+1)
                aItemName:=substr(A_LoopField,1,1) . "-" . aDirName
                aUUID:=UUIDCreate()
                GuiControlGet,aCompare,,Compare
                GuiControlGet,aSynchronize,,Synchronize
                aSourceDir:=A_LoopField
                GuiControlGet,aDirectionDir,,DirectionDir
                GuiControlGet,aErrorsIgnore,,ErrorsIgnore
                GuiControlGet,aProgressDialogMinimized,,ProgressDialogMinimized
                GuiControlGet,aProgressDialogAutoClose,,ProgressDialogAutoClose
                GuiControlGet,aErrorDialog,,ErrorDialog
                GuiControlGet,aPostSyncAction,,PostSyncAction
                aDirectionDir:=aDirectionDir . "\" . aDirName
                MsgBox, 36, 提示, 是否创建以下备份项目:`n--------------------------------------`n【项目名称】:%aItemName%`n【源文件夹】:%aSourceDir%`n【目标目录】:%aDirectionDir%
                ifmsgbox,no
                    continue
                if (aCompare="文件时间和大小")
                    aCompare:="TimeAndSize"
                else if (aCompare="文件内容")
                    aCompare:="Content"
                else if (aCompare="文件大小")
                    aCompare:="Size"
                if (aSynchronize="双向  <->")
                    aSynchronize:="TwoWay"
                else if (aSynchronize="镜像  ->")
                    aSynchronize:="Mirror"
                else if (aSynchronize="更新  >")
                    aSynchronize:="Update"
                if (aErrorDialog="取消备份")
                    aErrorDialog:="Cancel"
                else
                    aErrorDialog:="Show"
                if (aPostSyncAction="系统休眠")
                    aPostSyncAction:="Sleep"
                else if (aPostSyncAction="系统关机")
                    aPostSyncAction:="Shutdown"
                else 
                    aPostSyncAction:="None"
                aErrorsIgnore:=cBool(aErrorsIgnore)
                aProgressDialogMinimized:=cBool(aProgressDialogMinimized)
                aProgressDialogAutoClose:=cBool(aProgressDialogAutoClose)
                aBackupItem:=new BackupItem(aUUID,aItemName,aCompare,aSynchronize,aSourceDir,aDirectionDir,aErrorsIgnore,aProgressDialogMinimized,aProgressDialogAutoClose,aErrorDialog,aPostSyncAction)
                GuiControlGet,aProject_Sel,,Project_Sel
                HasProject:=0
                loop,% ProjectArray.length()
                {
                    if (ProjectArray[A_index].Name=aProject_Sel){
                        ProjectArray[A_index].Items.push(aBackupItem)
                        HasProject:=1
                        break
                    }
                }
                if (!HasProject) {
                        Project:={}
                        Project.Items:={}
                        Project.Name:=aProject_Sel
                        Project.LastBuckupTime:=""
                        Project.Items.push(aBackupItem)
                        ProjectArray.push(Project)
                }
                Item_List.= "|" aItemName
                GuiControl,,Item_Sel,|
                GuiControl,,Item_Sel,%Item_List%
                ;~ GuiControl,ChooseString,Item_Sel,%aItemName%
                ;~ gosub,备份项目_变动
                
            } else {
                SplitPath,A_LoopField,,MyOutDir,MyOutExt,MyOutNameNoExt
                If InStr("ffs_gui,ffs_batch", MyOutExt) {   ;如果FreeFileSync文件
                    aBackupItem:=ReadXMLToBackupItem(A_LoopField)
                    aItemName:=MyOutNameNoExt
                    aBackupItem.ItemName:=aItemName
                    GuiControlGet,aProject_Sel,,Project_Sel
                    HasProject:=0
                    loop,% ProjectArray.length()
                    {
                        if (ProjectArray[A_index].Name=aProject_Sel){
                            ProjectArray[A_index].Items.push(aBackupItem)
                            HasProject:=1
                            break
                        }
                    }
                    if (!HasProject) {
                        Project:={}
                        Project.Items:={}
                        Project.Name:=aProject_Sel
                        Project.LastBuckupTime:=""
                        Project.Items.push(aBackupItem)
                        ProjectArray.push(Project)
                    }
                    Item_List.= "|" aItemName
                    GuiControl,,Item_Sel,|
                    GuiControl,,Item_Sel,%Item_List%
                    ;~ GuiControl,ChooseString,Item_Sel,%aItemName%
                    ;~ gosub,备份项目_变动
                }
            }
        }
        GuiControl,ChooseString,Item_Sel,%aItemName%
        gosub,备份项目_变动
        
    } else {    ;单个文件
        ;判断是不是文件夹
        If InStr(FileExist(MySel), "D") { ;区分是否文件夹,Attrib= D ,则是文件夹
            if GetKeyState("Ctrl"){ ;检测是否按住Ctrl键
                GuiControl,,DirectionDir,%MySel%
                return
            } else {
                GuiControlGet,DirectionDir,,DirectionDir
                if (DirectionDir=""){
                    MsgBox, 48, 提示, 请先选择【目标目录】
                    return
                }
                if RegExMatch(MySel,"i)[a-zA-Z]\:\\"){   ;如果是盘符
                    aDirName:=""
                    aItemName:=substr(MySel,1,1) . "-" . aDirName
                } else {
                    aDirName:="\" . substr(MySel,instr(MySel,"\",,0,1)+1)
                    aItemName:=substr(MySel,1,1) . "-" . aDirName
                }
                GuiControl,,ItemName,%aItemName%
                GuiControl,,SourceDir,%MySel%
                GuiControlGet,DirectionDir,,DirectionDir
                GuiControl,,DirectionDir,%DirectionDir%%aDirName%
                GuiControlGet,Auto,,Auto
                if Auto {   ;如果自动批量
                    aUUID:=UUIDCreate()
                    GuiControlGet,aCompare,,Compare
                    GuiControlGet,aSynchronize,,Synchronize
                    GuiControlGet,aSourceDir,,SourceDir
                    GuiControlGet,aDirectionDir,,DirectionDir
                    GuiControlGet,aErrorsIgnore,,ErrorsIgnore
                    GuiControlGet,aProgressDialogMinimized,,ProgressDialogMinimized
                    GuiControlGet,aProgressDialogAutoClose,,ProgressDialogAutoClose
                    GuiControlGet,aErrorDialog,,ErrorDialog
                    GuiControlGet,aPostSyncAction,,PostSyncAction
                    if(aItemName="" or aSourceDir="" or aDirectionDir="") {
                        MsgBox, 0, 提示, 【项目名称】或【源文件夹】或【目标目录】为空,请重新输入
                        return
                    }
                    if (aCompare="文件时间和大小")
                        aCompare:="TimeAndSize"
                    else if (aCompare="文件内容")
                        aCompare:="Content"
                    else if (aCompare="文件大小")
                        aCompare:="Size"
                    if (aSynchronize="双向  <->")
                        aSynchronize:="TwoWay"
                    else if (aSynchronize="镜像  ->")
                        aSynchronize:="Mirror"
                    else if (aSynchronize="更新  >")
                        aSynchronize:="Update"
                    if (aErrorDialog="取消备份")
                        aErrorDialog:="Cancel"
                    else
                        aErrorDialog:="Show"
                    if (aPostSyncAction="系统休眠")
                        aPostSyncAction:="Sleep"
                    else if (aPostSyncAction="系统关机")
                        aPostSyncAction:="Shutdown"
                    else 
                        aPostSyncAction:="None"
                    aErrorsIgnore:=cBool(aErrorsIgnore)
                    aProgressDialogMinimized:=cBool(aProgressDialogMinimized)
                    aProgressDialogAutoClose:=cBool(aProgressDialogAutoClose)
                    aBackupItem:=new BackupItem(aUUID,aItemName,aCompare,aSynchronize,aSourceDir,aDirectionDir,aErrorsIgnore,aProgressDialogMinimized,aProgressDialogAutoClose,aErrorDialog,aPostSyncAction)
                    GuiControlGet,aProject_Sel,,Project_Sel
                    HasProject:=0
                    loop,% ProjectArray.length()
                    {
                        if (ProjectArray[A_index].Name=aProject_Sel){
                            ProjectArray[A_index].Items.push(aBackupItem)
                            HasProject:=1
                            break
                        }
                    }
                    if (!HasProject) {
                        Project:={}
                        Project.Items:={}
                        Project.Name:=aProject_Sel
                        Project.LastBuckupTime:=""
                        Project.Items.push(aBackupItem)
                        ProjectArray.push(Project)
                    }
                    Item_List.= "|" aItemName
                    GuiControl,,Item_Sel,|
                    GuiControl,,Item_Sel,%Item_List%
                    GuiControl,ChooseString,Item_Sel,%aItemName%
                    gosub,备份项目_变动
                }
            }
        } else {
            SplitPath,MySel,,MyOutDir,MyOutExt,MyOutNameNoExt
            If InStr("ffs_gui,ffs_batch", MyOutExt) {   ;如果FreeFileSync文件
                aBackupItem:=ReadXMLToBackupItem(MySel)
                aItemName:=MyOutNameNoExt
                aBackupItem.ItemName:=aItemName
                GuiControlGet,aProject_Sel,,Project_Sel
                HasProject:=0
                loop,% ProjectArray.length()
                {
                    if (ProjectArray[A_index].Name=aProject_Sel){
                        ProjectArray[A_index].Items.push(aBackupItem)
                        HasProject:=1
                        break
                    }
                }
                if (!HasProject) {
                    Project:={}
                    Project.Items:={}
                    Project.Name:=aProject_Sel
                    Project.LastBuckupTime:=""
                    Project.Items.push(aBackupItem)
                    ProjectArray.push(Project)
                }
                Item_List.= "|" aItemName
                GuiControl,,Item_Sel,|
                GuiControl,,Item_Sel,%Item_List%
                GuiControl,ChooseString,Item_Sel,%aItemName%
                gosub,备份项目_变动
            }
        }
        ;~ GuiControl,ChooseString,Item_Sel,%aItemName%
        ;~ gosub,备份项目_变动
    }
return
;}

GuiContextMenu:     ;{右键菜单-备份项目列表
	if (A_GuiControl="Item_Sel") {
		Menu,MyRightMenu,add
		Menu,MyRightMenu,DeleteAll
		Menu,MyRightMenu,add,执行选中备份,MenuHalder_Run
		Menu,MyRightMenu,add
		Menu,MyRightMenu,add,删除选中备份,MenuHalder_Del
        Menu,MyRightMenu,add
		Menu,MyRightMenu,add,比较选中文件夹,MenuHalder_Compare
		menu,MyRightMenu,Show
	}
return
;}

MenuHalder_Run:     ;{右键菜单处理:执行选中备份
    GuiControlGet,Project_Sel,,Project_Sel
    GuiControlGet,Item_Sel,,Item_Sel
    GuiControlGet,AppPath,,AppPath
    if (AppPath=""){
        MsgBox, 0, 提示, 请先指定FreeFileSync主程序目录
        return
    }
    MsgBox, 36, 提示, 确认执行【%Item_Sel%】备份项目?
    IfMsgBox,yes
    {
        BackupItemXML:=DeleteAllSpecialStringForFileName(Item_Sel)
        FileRemoveDir, %A_Temp%\Kawvin_FFSBatch, 1
		FileCreateDir, %A_Temp%\Kawvin_FFSBatch
        BackupItemXML=%A_Temp%\Kawvin_FFSBatch\%BackupItemXML%.ffs_batch
        WriteBackItemToXML(Project_Sel,Item_Sel,BackupItemXML)
        runwait,"%AppPath%"  "%BackupItemXML%"
        FileRemoveDir, %A_Temp%\Kawvin_FFSBatch, 1
        
    }
return
;}

MenuHalder_Del:     ;{右键菜单处理:删除选中备份
    GuiControlGet,Project_Sel,,Project_Sel
    GuiControlGet,Item_Sel,,Item_Sel
    MsgBox, 36, 提示, 确认删除【%Item_Sel%】备份项目?
    IfMsgBox,yes
    {
        BreakMark:=0
        loop,% ProjectArray.length()
        {
            aProject:=ProjectArray[A_index]
            AIndex:=A_index
            if (aProject.Name!=Project_Sel)
                continue
            aItem:=aProject.Items
            loop,% aItem.Length()
            {
                if(aItem[A_index]["ItemName"]=Item_Sel) {
                    ProjectArray[AIndex].Items.removeat(A_index)
                    BreakMark:=1
                    break
                }
            }
            if BreakMark
                break
        }
        if regexmatch(Item_List, "(\|)" . Item_Sel . "(\|)")
            Item_List:=RegExReplace(Item_List,"(\|)" . Item_Sel,"") 
        if regexmatch(Item_List, "^" . Item_Sel .  "(\|)")
            Item_List:=RegExReplace(Item_List,Item_Sel  .  "(\|)","") 
        if regexmatch(Item_List, "(\|)" . Item_Sel . "$")
            Item_List:=RegExReplace(Item_List,"(\|)" . Item_Sel,"") 
        GuiControl,,Item_Sel,|
        GuiControl,,Item_Sel,%Item_List%
        Guicontrol,Choose,Item_Sel,1
        gosub,备份项目_变动
    }
return
;}

MenuHalder_Compare:     ;{右键菜单处理:删除选中备份
    BCAppPath=.\Beyond_Compare\BCompare.exe
    IfNotExist,%BCAppPath%
    {
        MsgBox, 64, 提示, 【%BCAppPath%】软件不存在
        return
    }
    GuiControlGet,Project_Sel,,Project_Sel
    GuiControlGet,Item_Sel,,Item_Sel
    
    global ProjectArray
    BreakMark:=0
    loop,% ProjectArray.length()
    {
        aProject:=ProjectArray[A_index]
        if (aProject.Name!=Project_Sel)
            continue
        aItem:=aProject.Items
        loop,% aItem.Length()
        {
            if(aItem[A_index]["ItemName"]=Item_Sel) {
                BCompareLeftFile:=aItem[A_index]["SourceDir"]
                BCompareRightFile:=aItem[A_index]["DirectionDir"]
                BreakMark:=1
                break
            }
        }
        if BreakMark
            break
    }
    ;~ msgbox % BCompareLeftFile
    ;~ msgbox % BCompareRightFile
    NotExit:=0
    IfNotExist,%BCompareLeftFile%
        NotExit:=1
    IfNotExist,%BCompareRightFile%
        NotExit:=1
    if(NotExit=1){
        MsgBox, 64, 提示, 源文件夹或目录文件夹不存在
        return
    }
    Run,%  BCAppPath " """ BCompareLeftFile """ """ BCompareRightFile """"
return
;}

一键备份:   ;{
    GuiControlGet,Project_Sel,,Project_Sel
    GuiControlGet,AppPath,,AppPath
    if (AppPath=""){
        MsgBox, 0, 提示, 请先指定FreeFileSync主程序目录
        return
    }
    MsgBox, 36, 提示, 确认执行【%Project_Sel%】备份计划下的所有备份项目?
    IfMsgBox,yes
    {
        FileRemoveDir, %A_Temp%\Kawvin_FFSBatch, 1
		FileCreateDir, %A_Temp%\Kawvin_FFSBatch
        GuiControl,Show,Progress1
        ItemCount:=0
        Loop,parse,Item_List,|
        {
            if (A_LoopField="")
                continue
            ItemCount++
        }
        Loop,parse,Item_List,|
        {
            if (A_LoopField="")
                continue
            BackupItemXML:=DeleteAllSpecialStringForFileName(A_LoopField)
            BackupItemXML=%A_Temp%\Kawvin_FFSBatch\%BackupItemXML%.ffs_batch
            WriteBackItemToXML(Project_Sel,A_LoopField,BackupItemXML)
            runwait,"%AppPath%"  "%BackupItemXML%"
            ProgressPercent:=a_index/ItemCount*100
            GuiControl,,Progress1,%ProgressPercent%
        }
        FileRemoveDir, %A_Temp%\Kawvin_FFSBatch, 1
        ;写入最后备份时间
        MyNowTime=%A_YYYY%.%A_MM%.%A_DD% %A_Hour%:%A_Min%:%A_Sec%
        WriteLastBuckupTimeToXML(BackupXML,Project_Sel,MyNowTime)
        GuiControl,,LastBackTime,最近备份:%MyNowTime%
        ;调整进度条
        GuiControl,,Progress1,100
        GuiControlget,ShutdownAfterfinish,,ShutdownAfterfinish
        if (ShutdownAfterfinish=1)
            MyFun_ShutDown(30)
        else
            msgbox ,备份完成
        GuiControl,,Progress1,0
        GuiControl,hide,Progress1
    }
    
return
;}

备份计划_变动:    ;{【2】备份计划-变动
    GuiControlGet,Project_Sel,,Project_Sel
    Item_List:=""
    loop,% ProjectArray.length()
    {
        aProject:=ProjectArray[A_index]
        if (aProject.Name!=Project_Sel)
            continue
        LastBackTime:=aProject.LastBuckupTime
        aItem:=aProject.Items
        loop,% aItem.Length()
        {
            Item_List:=Item_List  .  aItem[A_index]["ItemName"] .  "|"
        }
    }
    gosub,窗体初始化
    GuiControl,,Item_Sel,|
    GuiControl,,Item_Sel,%Item_List%
    GuiControl,,LastBackTime,最近备份:%LastBackTime%
return
;}

备份项目_变动:       ;{【2】备份项目-变动
    GuiControlGet,Project_Sel,,Project_Sel
    GuiControlGet,Item_Sel,,Item_Sel
    gosub,窗体初始化
    loop,% ProjectArray.length()
    {
        aProject:=ProjectArray[A_index]
        if (aProject.Name!=Project_Sel)
            continue
        LastBackTime:=aProject.LastBuckupTime
        aItem:=aProject.Items
        loop,% aItem.Length()
        {
            if(aItem[A_index]["ItemName"]!=Item_Sel)
                continue
            GuiControl,,UUID,% aItem[A_index]["UUID"] 
            GuiControl,,ItemName,% aItem[A_index]["ItemName"] 
            if (aItem[A_index]["Compare"] ="TimeAndSize")
                GuiControl,Choose,Compare,1
            else if (aItem[A_index]["Compare"] ="Content")
                GuiControl,Choose,Compare,2
            else if (aItem[A_index]["Compare"] ="Size")
                GuiControl,Choose,Compare,3
            if (aItem[A_index]["Synchronize"] ="TwoWay")
                GuiControl,Choose,Synchronize,1
            else if (aItem[A_index]["Synchronize"] ="Mirror")
                GuiControl,Choose,Synchronize,2
            else if (aItem[A_index]["Synchronize"] ="Update")
                GuiControl,Choose,Synchronize,3
            GuiControl,,SourceDir,% aItem[A_index]["SourceDir"] 
            GuiControl,,DirectionDir,% aItem[A_index]["DirectionDir"] 
            if (aItem[A_index]["ErrorsIgnore"] ="true")
                GuiControl,,ErrorsIgnore,1
            else
                GuiControl,,ErrorsIgnore,0
            if (aItem[A_index]["ProgressDialogMinimized"] ="true")
                GuiControl,,ProgressDialogMinimized,1
            else
                GuiControl,,ProgressDialogMinimized,0
            if (aItem[A_index]["ProgressDialogAutoClose"] ="true")
                GuiControl,,ProgressDialogAutoClose,1
            else
                GuiControl,,ProgressDialogAutoClose,0
            if (aItem[A_index]["ErrorDialog"] ="Show")
                GuiControl,Choose,ErrorDialog,1
            else if (aItem[A_index]["ErrorDialog"] ="Cancel")
                GuiControl,Choose,ErrorDialog,2
            if (aItem[A_index]["PostSyncAction"] ="None")
                GuiControl,Choose,PostSyncAction,1
            else if (aItem[A_index]["PostSyncAction"] ="Sleep")
                GuiControl,Choose,PostSyncAction,2
            else if (aItem[A_index]["PostSyncAction"] ="Shutdown")
                GuiControl,Choose,PostSyncAction,3
        }
    }
return
;}

窗体初始化:      ;{全部窗体数据清空
    GuiControl,,UUID,
    GuiControl,,ItemName,
    GuiControl,Choose,Compare,1
    GuiControl,Choose,Synchronize,1
    GuiControl,,SourceDir,
    GuiControl,,DirectionDir,
    GuiControl,,ErrorsIgnore,1
    GuiControl,,ProgressDialogMinimized,0
    GuiControl,,ProgressDialogAutoClose,1
    GuiControl,Choose,ErrorDialog,1
    GuiControl,Choose,PostSyncAction,1
    ;~ GuiControl,,Auto,1
return
;}

保存到XML:   ;{
    FileDelete,%BackupXML%
    FileAppend,<?xml version="1.0" encoding="utf-8"?>`n,%BackupXML%,UTF-8
    FileAppend,<Kawvin_BatchBackup>`n,%BackupXML%,UTF-8
    FileAppend,`t<FreeFileSyncPath>%AppPath%</FreeFileSyncPath>`n,%BackupXML%,UTF-8
    loop,% ProjectArray.length()
    {
        aProject:=ProjectArray[A_index]
        AIndex:=A_index
        aName:=aProject.Name
        aLastBuckupTime:=aProject.LastBuckupTime
        FileAppend,`t<BackupProject Name=`"%aName%`" LastBuckupTime=`"%aLastBuckupTime%`">`n,%BackupXML%,UTF-8
        aItem:=aProject.Items
        loop,% aItem.Length()
        {
            aUUID:=aItem[A_index]["UUID"]
            FileAppend,`t`t<Item UUID=`"%aUUID%`">`n,%BackupXML%,UTF-8
            aItemName:=aItem[A_index]["ItemName"]
            FileAppend,`t`t`t<ItemName>%aItemName%</ItemName>`n,%BackupXML%,UTF-8
            aCompare:=aItem[A_index]["Compare"]
            FileAppend,`t`t`t<Compare>%aCompare%</Compare>`n,%BackupXML%,UTF-8
            aSynchronize:=aItem[A_index]["Synchronize"]
            FileAppend,`t`t`t<Synchronize>%aSynchronize%</Synchronize>`n,%BackupXML%,UTF-8
            aSourceDir:=aItem[A_index]["SourceDir"]
            FileAppend,`t`t`t<SourceDir>%aSourceDir%</SourceDir>`n,%BackupXML%,UTF-8
            aDirectionDir:=aItem[A_index]["DirectionDir"]
            FileAppend,`t`t`t<DirectionDir>%aDirectionDir%</DirectionDir>`n,%BackupXML%,UTF-8
            aErrorsIgnore:=aItem[A_index]["ErrorsIgnore"]
            FileAppend,`t`t`t<Errors Ignore=`"%aErrorsIgnore%`"/>`n,%BackupXML%,UTF-8
            aProgressDialogMinimized:=aItem[A_index]["ProgressDialogMinimized"]
            aProgressDialogAutoClose:=aItem[A_index]["ProgressDialogAutoClose"]
            FileAppend,`t`t`t<ProgressDialog Minimized=`"%aProgressDialogMinimized%`" AutoClose=`"%aProgressDialogAutoClose%`"/>`n,%BackupXML%,UTF-8
            aErrorDialog:=aItem[A_index]["ErrorDialog"]
            FileAppend,`t`t`t<ErrorDialog>%aErrorDialog%</ErrorDialog>`n,%BackupXML%,UTF-8
            aPostSyncAction:=aItem[A_index]["PostSyncAction"]
            FileAppend,`t`t`t<PostSyncAction>%aPostSyncAction%</PostSyncAction>`n,%BackupXML%,UTF-8
            FileAppend,`t`t</Item>`n,%BackupXML%,UTF-8
        }
        FileAppend,`t</BackupProject>`n,%BackupXML%,UTF-8
    }
    FileAppend,</Kawvin_BatchBackup>,%BackupXML%,UTF-8
    MsgBox, 0, 提示, 保存到XML文件完成!
return
;}

确认修改:   ;{
    GuiControlGet,aUUID,,UUID
    GuiControlGet,aProject_Sel,,Project_Sel
    GuiControlGet,aItemName,,ItemName
    GuiControlGet,aCompare,,Compare
    GuiControlGet,aSynchronize,,Synchronize
    GuiControlGet,aSourceDir,,SourceDir
    GuiControlGet,aDirectionDir,,DirectionDir
    GuiControlGet,aErrorsIgnore,,ErrorsIgnore
    GuiControlGet,aProgressDialogMinimized,,ProgressDialogMinimized
    GuiControlGet,aProgressDialogAutoClose,,ProgressDialogAutoClose
    GuiControlGet,aErrorDialog,,ErrorDialog
    GuiControlGet,aPostSyncAction,,PostSyncAction
    if(aItemName="" or aSourceDir="" or aDirectionDir="") {
        MsgBox, 0, 提示, 【项目名称】或【源文件夹】或【目标目录】为空,请重新输入
        return
    }
    if (aCompare="文件时间和大小")
        aCompare:="TimeAndSize"
    else if (aCompare="文件内容")
        aCompare:="Content"
    else if (aCompare="文件大小")
        aCompare:="Size"
    if (aSynchronize="双向  <->")
        aSynchronize:="TwoWay"
    else if (aSynchronize="镜像  ->")
        aSynchronize:="Mirror"
    else if (aSynchronize="更新  >")
        aSynchronize:="Update"
    if (aErrorDialog="取消备份")
        aErrorDialog:="Cancel"
    else
        aErrorDialog:="Show"
    if (aPostSyncAction="系统休眠")
        aPostSyncAction:="Sleep"
    else if (aPostSyncAction="系统关机")
        aPostSyncAction:="Shutdown"
    else 
        aPostSyncAction:="None"
    aErrorsIgnore:=cBool(aErrorsIgnore)
    aProgressDialogMinimized:=cBool(aProgressDialogMinimized)
    aProgressDialogAutoClose:=cBool(aProgressDialogAutoClose)
    BreakMark:=0
    loop,% ProjectArray.length()
    {
        
        aProject:=ProjectArray[A_index]
        AIndex:=A_index
        if (aProject.Name!=Project_Sel)
            continue
        aItem:=aProject.Items
        loop,% aItem.Length()
        {
            if(aItem[A_index]["UUID"]=aUUID) {
                ProjectArray[AIndex].Items[A_index]["ItemName"]:=aItemName
                ProjectArray[AIndex].Items[A_index]["Compare"]:=aCompare
                ProjectArray[AIndex].Items[A_index]["Synchronize"]:=aSynchronize
                ProjectArray[AIndex].Items[A_index]["SourceDir"]:=aSourceDir
                ProjectArray[AIndex].Items[A_index]["DirectionDir"]:=aDirectionDir
                ProjectArray[AIndex].Items[A_index]["ErrorsIgnore"]:=aErrorsIgnore
                ProjectArray[AIndex].Items[A_index]["ProgressDialogMinimized"]:=aProgressDialogMinimized
                ProjectArray[AIndex].Items[A_index]["ProgressDialogAutoClose"]:=aProgressDialogAutoClose
                ProjectArray[AIndex].Items[A_index]["ErrorDialog"]:=aErrorDialog
                ProjectArray[AIndex].Items[A_index]["PostSyncAction"]:=aPostSyncAction
                BreakMark:=1
                break
            }
        }
        if BreakMark
            break
    }
    gosub,备份计划_变动
    GuiControl,ChooseString,Item_Sel,%aItemName%
    gosub,备份项目_变动
return
;}

ReadXMLToArray(BackupXML){    ;函数:读取XML文件到数组
    global ProjectArray
    global AppPath
    global Project_List
    ProjectArray:={}
    xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
    xmlDoc.async := false
    xmlDoc.load(BackupXML)
    AppPath:=xmlDoc.selectSingleNode("//FreeFileSyncPath") .text
    ProjectNodes:=xmlDoc.selectNodes("//BackupProject")
    for ProjectNode in ProjectNodes
    {
        Project:={}
        Project.Items:={}
        Project.Name:=ProjectNode.getAttribute("Name")
        Project_List.= Project.Name "|"
        Project.LastBuckupTime:=ProjectNode.getAttribute("LastBuckupTime")
        ItemNodes:=ProjectNode.childNodes
        for ItemNode in ItemNodes
        {
            aUUID:=ItemNode.getAttribute("UUID")
            aItemName:=ItemNode.selectSingleNode("ItemName").text
            aCompare:=ItemNode.selectSingleNode("Compare").text
            aSynchronize:=ItemNode.selectSingleNode("Synchronize").text
            aSourceDir:=ItemNode.selectSingleNode("SourceDir").text
            aDirectionDir:=ItemNode.selectSingleNode("DirectionDir").text
            aErrorsIgnore:=ItemNode.selectSingleNode("Errors").getAttribute("Ignore")
            aProgressDialogMinimized:=ItemNode.selectSingleNode("ProgressDialog").getAttribute("Minimized")
            aProgressDialogAutoClose:=ItemNode.selectSingleNode("ProgressDialog").getAttribute("AutoClose")
            aErrorDialog:=ItemNode.selectSingleNode("ErrorDialog").text
            aPostSyncAction:=ItemNode.selectSingleNode("PostSyncAction").text
            aBackupItem:=new BackupItem(aUUID,aItemName,aCompare,aSynchronize,aSourceDir,aDirectionDir,aErrorsIgnore,aProgressDialogMinimized,aProgressDialogAutoClose,aErrorDialog,aPostSyncAction)
                Project.Items.push(aBackupItem)                
        }
        ProjectArray.push(Project)
    }
}

ReadXMLToBackupItem(XMLFile){
    xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
    xmlDoc.async := false
    xmlDoc.load(XMLFile)
    aUUID:=UUIDCreate()
    aItemName:=""
    XmlFormat:=xmlDoc.selectSingleNode("/FreeFileSync").getAttribute("XmlFormat")
    if (XmlFormat=12) {
        aCompare:=xmlDoc.selectSingleNode("/FreeFileSync/Compare/Variant").text
        aSynchronize:=xmlDoc.selectSingleNode("/FreeFileSync/Synchronize/Variant").text
        aSourceDir:=xmlDoc.selectSingleNode("/FreeFileSync/FolderPairs/Pair/Left").text
        aDirectionDir:=xmlDoc.selectSingleNode("/FreeFileSync/FolderPairs/Pair/Right").text
        aErrorsIgnore:=xmlDoc.selectSingleNode("/FreeFileSync/Errors").getAttribute("Ignore")
        try
            aProgressDialogMinimized:=xmlDoc.selectSingleNode("/FreeFileSync/Batch/ProgressDialog").getAttribute("Minimized")
        catch e
            aProgressDialogMinimized:="false"
        try
            aProgressDialogAutoClose:=xmlDoc.selectSingleNode("/FreeFileSync/Batch/ProgressDialog").getAttribute("AutoClose")
        catch e
            aProgressDialogMinimized:="true"
        try
            aErrorDialog:=xmlDoc.selectSingleNode("/FreeFileSync/Batch/ErrorDialog").text
        catch e
            aProgressDialogMinimized:="show"
        try
            aPostSyncAction:=xmlDoc.selectSingleNode("/FreeFileSync/Batch/PostSyncAction").text
        catch e
            aProgressDialogMinimized:="none"
    } else if (XmlFormat=11) {
        
    } else if (XmlFormat=10) {
        
    } else if (XmlFormat=9) {
        
    } else if (XmlFormat=8) {
        aCompare:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/Comparison/Variant").text
        aSynchronize:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/SyncConfig/Variant").text
        aSourceDir:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/FolderPairs/Pair/Left").text
        aDirectionDir:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/FolderPairs/Pair/Right").text
        aErrorsIgnore:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/IgnoreErrors").text
        try
            aProgressDialogMinimized:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/RunMinimized").text
        catch e
            aProgressDialogMinimized:="false"
        try
            aProgressDialogAutoClose:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/ProgressDialog").getAttribute("AutoClose")
        catch e
            aProgressDialogMinimized:="true"
        try
            aErrorDialog:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/ErrorDialog").text
        catch e
            aProgressDialogMinimized:="show"
        try
            aPostSyncAction:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/PostSyncAction").text
        catch e
            aProgressDialogMinimized:="none"
    } else if (XmlFormat=7) {
        aCompare:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/Comparison/Variant").text
        aSynchronize:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/SyncConfig/Variant").text
        aSourceDir:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/FolderPairs/Pair/Left").text
        aDirectionDir:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/FolderPairs/Pair/Right").text
        aErrorsIgnore:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/IgnoreErrors").text
        try
            aProgressDialogMinimized:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/RunMinimized").text
        catch e
            aProgressDialogMinimized:="false"
        try
            aProgressDialogAutoClose:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/ProgressDialog").getAttribute("AutoClose")
        catch e
            aProgressDialogMinimized:="true"
        try
            aErrorDialog:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/ErrorDialog").text
        catch e
            aProgressDialogMinimized:="show"
        try
            aPostSyncAction:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/PostSyncAction").text
        catch e
            aProgressDialogMinimized:="none"
    } else if (XmlFormat=6) {
        aCompare:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/Comparison/Variant").text
        aSynchronize:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/SyncConfig/Variant").text
        aSourceDir:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/FolderPairs/Pair/Left").text
        aDirectionDir:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/FolderPairs/Pair/Right").text
        aErrorsIgnore:=xmlDoc.selectSingleNode("/FreeFileSync/MainConfig/IgnoreErrors").text
        try
            aProgressDialogMinimized:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/RunMinimized").text
        catch e
            aProgressDialogMinimized:="false"
        try
            aProgressDialogAutoClose:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/ProgressDialog").getAttribute("AutoClose")
        catch e
            aProgressDialogMinimized:="true"
        try
            aErrorDialog:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/ErrorDialog").text
        catch e
            aProgressDialogMinimized:="show"
        try
            aPostSyncAction:=xmlDoc.selectSingleNode("/FreeFileSync/BatchConfig/PostSyncAction").text
        catch e
            aProgressDialogMinimized:="none"
    } else  {
        
    }
    aBackupItem:=new BackupItem(aUUID,aItemName,aCompare,aSynchronize,aSourceDir,aDirectionDir,aErrorsIgnore,aProgressDialogMinimized,aProgressDialogAutoClose,aErrorDialog,aPostSyncAction)
    return aBackupItem
}

WriteLastBuckupTimeToXML(aXML,aProjectName,aLastBuckupTime){ ;写入内容到XML文件,参数aXML:文件名,aNode:节点,aType:类型(Text或属性),aValue:值
    xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
    xmlDoc.async := false
    xmlDoc.load(aXML)
    ProjectNodes:=xmlDoc.selectNodes("//BackupProject")
    loop,% ProjectNodes.length()
    {
        aNode := ProjectNodes.item(A_Index-1)
        if (aProjectName= aNode.getAttribute("Name"))
            ProjectNodes.item(A_Index-1).setAttribute("LastBuckupTime", aLastBuckupTime)
        break
    }
    xmlDoc.save(aXML)
}

WriteBackItemToXML(Project_Sel,aItemName,BackupItemXML){
    global ProjectArray
    BreakMark:=0
    loop,% ProjectArray.length()
    {
        aProject:=ProjectArray[A_index]
        if (aProject.Name!=Project_Sel)
            continue
        aItem:=aProject.Items
        loop,% aItem.Length()
        {
            if(aItem[A_index]["ItemName"]=aItemName) {
                ;~ aItemName:=aItem[A_index]["ItemName"]
                aCompare:=aItem[A_index]["Compare"]
                aSynchronize:=aItem[A_index]["Synchronize"]
                aSourceDir:=aItem[A_index]["SourceDir"]
                aDirectionDir:=aItem[A_index]["DirectionDir"]
                aErrorsIgnore:=aItem[A_index]["ErrorsIgnore"]
                aProgressDialogMinimized:=aItem[A_index]["ProgressDialogMinimized"]
                aProgressDialogAutoClose:=aItem[A_index]["ProgressDialogAutoClose"]
                aErrorDialog:=aItem[A_index]["ErrorDialog"]
                aPostSyncAction:=aItem[A_index]["PostSyncAction"]
                
                FileAppend,<?xml version="1.0" encoding="utf-8"?>`n,%BackupItemXML%,UTF-8
                FileAppend,<FreeFileSync XmlType="BATCH" XmlFormat="12">`n,%BackupItemXML%,UTF-8
                FileAppend,`t<Compare>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<Variant>%aCompare%</Variant>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<Symlinks>Exclude</Symlinks>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<IgnoreTimeShift/>`n,%BackupItemXML%,UTF-8
                FileAppend,`t</Compare>`n,%BackupItemXML%,UTF-8
                FileAppend,`t<Synchronize>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<Variant>%aSynchronize%</Variant>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<DetectMovedFiles>false</DetectMovedFiles>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<DeletionPolicy>RecycleBin</DeletionPolicy>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<VersioningFolder Style="Replace"/>`n,%BackupItemXML%,UTF-8
                FileAppend,`t</Synchronize>`n,%BackupItemXML%,UTF-8
                FileAppend,`t<Filter>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<Include>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>*</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t</Include>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<Exclude>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>\System Volume Information\</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>\$Recycle.Bin\</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>\RECYCLER\</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>\RECYCLED\</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>*\desktop.ini</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Item>*\thumbs.db</Item>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t</Exclude>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<TimeSpan Type="None">0</TimeSpan>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<SizeMin Unit="None">0</SizeMin>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<SizeMax Unit="None">0</SizeMax>`n,%BackupItemXML%,UTF-8
                FileAppend,`t</Filter>`n,%BackupItemXML%,UTF-8
                FileAppend,`t<FolderPairs>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<Pair>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Left>%aSourceDir%</Left>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t`t<Right>%aDirectionDir%</Right>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t</Pair>`n,%BackupItemXML%,UTF-8
                FileAppend,`t</FolderPairs>`n,%BackupItemXML%,UTF-8
                FileAppend,`t<Errors Ignore=`"%aErrorsIgnore%`" Retry="0" Delay="5"/>`n,%BackupItemXML%,UTF-8
                FileAppend,`t<PostSyncCommand Condition="Completion"/>`n,%BackupItemXML%,UTF-8
                FileAppend,`t<Batch>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<ProgressDialog Minimized=`"%aProgressDialogMinimized%`" AutoClose=`"%aProgressDialogAutoClose%`"/>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<ErrorDialog>%aErrorDialog%</ErrorDialog>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<PostSyncAction>%aPostSyncAction%</PostSyncAction>`n,%BackupItemXML%,UTF-8
                FileAppend,`t`t<LogfileFolder Limit="-1"/>`n,%BackupItemXML%,UTF-8
                FileAppend,`t</Batch>`n,%BackupItemXML%,UTF-8
                FileAppend,</FreeFileSync>,%BackupItemXML%,UTF-8
                BreakMark:=1
                break
            }
        }
        if BreakMark
            break
    }
}

/* Class:BackupItem
    类名:BackupItem
    作用:根据条件,智能进行场景切换,并执行操作
    作者: Kawvin
    版本: 0.1
    使用方法:aBackupItem:=new BackupItem(aUUID,aItemName,aCompare,aSynchronize,aSourceDir,aDirectionDir,aErrorsIgnore,aProgressDialogMinimized,aProgressDialogAutoClose,aErrorDialog,aPostSyncAction)
	参数说明:
        aUUID:UUID
		aItemName:名称
		aCompare :比较内容,TimeAndSize=文件时间及大小,Content=文件内容,Size=文件大小
		aSynchronize:备份方式,TwoWay=双向,Update=更新,Mirror=镜像
		aSourceDir:源文件夹
		aDirectionDir:目标目录
		aErrorsIgnore:是否忽略错误
		aProgressDialogMinimized:最小化处理对话框
		aProgressDialogAutoClose:自动关闭处理对话框
		aErrorDialog:出错操作,Show=显示对话框,Cancel=取消备份
        aPostSyncAction:运行完操作,sleep=系统休眠,Shutdown=系统关机
*/
class BackupItem{
	;~ static ItemName:=""
	;~ static Compare:=""
	;~ static Synchronize:=""
	;~ static SourceDir:=""
	;~ static DirectionDir:=""
	;~ static ErrorsIgnore:=""
	;~ static ProgressDialogMinimized:=""
	;~ static ProgressDialogAutoClose:=""
	;~ static ErrorDialog:=""
    ;~ static PostSyncAction:=""
	
	__New(aUUID,aItemName,aCompare:="TimeAndSize",aSynchronize:="TwoWay",aSourceDir:="",aDirectionDir:="",aErrorsIgnore:="true",aProgressDialogMinimized:="false",aProgressDialogAutoClose:="true",aErrorDialog:="",aPostSyncAction:="None"){
        this.UUID:=aUUID
		this.ItemName:=aItemName
		this.Compare:=aCompare
		this.Synchronize:=aSynchronize
		this.SourceDir:=aSourceDir
		this.DirectionDir:=aDirectionDir
		this.ErrorsIgnore:=aErrorsIgnore
		this.ProgressDialogMinimized:=aProgressDialogMinimized
		this.ProgressDialogAutoClose:=aProgressDialogAutoClose
		this.ErrorDialog:=aErrorDialog
        this.PostSyncAction:=aPostSyncAction
	}
}

UUIDCreate(mode:=1, format:="", ByRef UUID:=""){
	UuidCreate := "Rpcrt4\UuidCreate"
	if InStr("02", mode)
		UuidCreate .= mode? "Sequential" : "Nil"
	VarSetCapacity(UUID, 16, 0) ;// long(UInt) + 2*UShort + 8*UChar
	if (DllCall(UuidCreate, "Ptr", &UUID) == 0)
	&& (DllCall("Rpcrt4\UuidToString", "Ptr", &UUID, "UInt*", pString) == 0)
	{
		string := StrGet(pString)
		DllCall("Rpcrt4\RpcStringFree", "UInt*", pString)
		if InStr(format, "U")
			DllCall("CharUpper", "Ptr", &string)
		return InStr(format, "{") ? "{" . string . "}" : string
	}
}

cBool(aNum){    ;将数字0或1转换为false或true
    if (aNum=1)
        return "true"
    else
        return "false"
}

MyFun_ShutDown(Sec){
	global Timeout
	SetTimer, ChangeStatic1Text, 1000 
	Timeout:=Sec
	MsgBox, 4, 备份完成关机确认, 在【%Timeout%秒】内未点击【取消】,则自动关机, %Sec%
	ifmsgbox,no
		return
	shutdown,5
}

ChangeStatic1Text:  ;{
    IfWinNotExist, 备份完成关机确认
        return
    WinActivate 
    Timeout-=1
    ControlSetText, Static1, 在【%Timeout%秒】内未点击【取消】,则自动关机
return
;}

DeleteAllSpecialStringForFileName(aStr){    ;删除所有特殊的名称字符,\/*?:"<>|
    bStr:=StrReplace(aStr,"\","")
    bStr:=StrReplace(bStr,"/","")
    bStr:=StrReplace(bStr,"*","")
    bStr:=StrReplace(bStr,"?","")
    bStr:=StrReplace(bStr,":","")
    bStr:=StrReplace(bStr,"""","")
    bStr:=StrReplace(bStr,"<","")
    bStr:=StrReplace(bStr,">","")
    bStr:=StrReplace(bStr,"|","")
    return , bStr
}

给TA捐赠
共{{data.count}}人
人已捐赠
其他案例

Kawvin闪电粘贴V0.7

2022-4-27 17:09:02

其他

CapsLock键根据大小写状态改变光标样式

2022-5-1 10:33:19

8 条回复 A文章作者 M管理员
  1. hexuren
    1河许人给您打赏了¥2
  2. dbgba
    dbgba给您打赏了¥5
  3. aahk

    Kawvin批处理备份(FreeFileSync)V6.1.5 的使用感受:
    1、满意、好评,作者辛苦了,非常感谢作者的辛勤劳动和无私奉献。
    2、免费、开源,可以永久使用,确实是个宝。
    3、稳定高效简单易用,这个AutoHotkey脚本很稳定,很好用,FreeFileSync又是开源的 C++ 的源代码,很好很稳定。
    4、此ahk脚本没有定时同步功能,没有自动同步功能,没有后台静默同步功能。
    5、此ahk脚本没有连接群晖WebDAV功能,此ahk脚本没有连接群晖SFTP功能。

    我建议作者参考借鉴GoodSync和SyncBackPro 的界面和功能做出相应改进和优化。

  4. aahk

    建议添加命令行参数传递功能和全局快捷键功能

  5. aahk
    aahk给您打赏了¥2
  6. aahk

    建议添加后台定时自动静默备份指定的多个文件夹到多个目标位置的AutoHotkey脚本功能源代码片段

    • kawvin

      你这个做出来,就成了后台的实时备份系统了,和我原来的初衷有所不同,不过也是可以实现的,就是整个逻辑要修改一下了。

  7. doge

    高级啊,希望我有朝一日也能达到这么高的水平!!!

个人中心
购物车
优惠劵
有新私信 私信列表
搜索