// +build windows package main import ( "bufio" "database/sql" "errors" "fmt" _ "github.com/go-sql-driver/mysql" "github.com/lxn/walk" . "github.com/lxn/walk/declarative" "github.com/lxn/win" "github.com/mzky/zip" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" "io" "io/fs" "io/ioutil" "log" "os" "os/exec" "path/filepath" "runtime" "strings" "syscall" "time" ) var version = "V2021 1.0.1" var passwordname = "Qw^e1@10&++Hzb...?8" func (mw *myApp) aboutactionTriggered() { walk.MsgBox(mw.mw, "功能说明", strings.Join([]string{ "1. 启动、终止并设置 应用和数据库 服务", "2. 清除 浏览器和应用 缓存", "3. 设置 应用和数据库 内存大小", "4. 实现 数据备份 压缩备份库文件与备份照片", "5. 实现 数据还原 执行还原库文件与还原照片", fmt.Sprintf("版本:%s", version)}, "\n"), walk.MsgBoxIconQuestion) } type myApp struct { title string name string msg *walk.TextEdit mw *walk.MainWindow } type myService struct { text string serviceName string labelState *walk.Label btnRegister *walk.PushButton btnStart *walk.PushButton btnStop *walk.PushButton } var app myApp var service1, service3 myService // 该部分不存在最后 横线 (格式为 D:\hzb2021),使用时需要补充横线 var path string // 基础库部分脚本(除 a01 和 b01) var tableName = []string{ "a02", "a05", "a06", "a08", "a14", "a15", "a17", "a36", "a30", "a33", "a57", "a65", "a99z1", } // 统计部分脚本 var tableNameTj = []string{ "tj_un", "tb_set_unit", "tb_rpt_cv_cfg", "J2001", "J2002", "J2003", "J2004", "J2005", "J2006", "J2007", "J2008", "J2101", "J2102", "J2103", "J2104", "J2105", "J2106", "J2107", "J2108", "M_M01", "M_M02", "M_M03", "M_M04", "M_M05", "M_M06", "M_M07", "M_M09", "M_N01", "M_N02", "M_N03", "M_N04", "M_N05", "M_P01", "M_P02", "M_P03", "M_Q01", "M_Q02", "M_Q03", "M_Q04", "M_Q05", "M_Q06", "M_Q07", "M_Q08", "M_Q09", "M_Q10", "M_Q11", "M_Q12", "M_Q13", "inner_check_result", "outer_check_result", "statistics_state", "middleverify_error_list", "tj_tbsm_item_list", "tb_zyhz", } // init 初始化 func init() { app.title = "公务员管理系统-运行监控" app.name = "网新" service1 = myService{ text: "⚡数据存储库", serviceName: "GWY20_Mysql", } service3 = myService{ text: "⚡公务员系统", serviceName: "GWY20_Tomcat", } path, _ = os.Getwd() } // main 程序入口 func main() { _ = getWindows() runMain() } func runMain() { if e := HasHzb(); e != nil { walk.MsgBox(app.mw, "错误", "请先下载并安装 组工 软件,才可以正常使用软件!", walk.MsgBoxIconWarning) _ = OpenUrl("https://www.12371.cn/zgrjxz/gwywx/") return } if e := InHzb(); e != nil { walk.MsgBox(app.mw, "错误", "当前工具未在正确的位置!\n请将工具移至安装软件目录下(如:./hzb2020/HyServer.exe)。", walk.MsgBoxIconWarning) return } walk.App().SetProductName(app.title) walk.App().SetOrganizationName(app.name) walk.App().SetProductName(app.name) showMsg(fmt.Sprintf(" 当前获取的目录为:%s", path)) _ = service1.labelState.SetText("未安装") _ = service3.labelState.SetText("未安装") service1.btnRegister.Clicked().Attach(func() { registerService(service1) }) service1.btnStart.Clicked().Attach(func() { startService(service1) }) service1.btnStop.Clicked().Attach(func() { stopService(service1) }) service3.btnRegister.Clicked().Attach(func() { registerService(service3) }) service3.btnStart.Clicked().Attach(func() { startService(service3) }) service3.btnStop.Clicked().Attach(func() { stopService(service3) }) go flushServiceStat(service1) go flushServiceStat(service3) app.mw.Show() app.mw.Run() } // 初始始化窗体 func getWindows() error { icon, _ := walk.NewIconFromResourceId(3) err := MainWindow{ Visible: false, AssignTo: &app.mw, Title: app.title, Size: Size{Width: 500, Height: 360}, Font: Font{Family: "微软雅黑", PointSize: 9}, Icon: icon, Layout: VBox{}, MenuItems: []MenuItem{ Menu{ Text: "&编辑", // Image: "./image//media.png", Items: []MenuItem{ Separator{}, Action{ // Image: "./image//qinghuancun.png", Text: "清除缓存", OnTriggered: clearAll, }, Action{ // Image: "./image//beifen.png", Text: "数据备份", OnTriggered: dbBak, }, /*Action{ // Image: "./image//huanyuan.png", Text: "数据还原", OnTriggered: reDbBak, },*/ Action{ // Image: "./image//tuichu.png", Text: "退出", OnTriggered: func() { walk.App().Exit(0) }, }, }, }, Menu{ Text: "&设置", // Image: "./image//shezhi.png", Items: []MenuItem{ Separator{}, Action{ // Image: "./image//shujuku.png", Text: "设置数据库内存", OnTriggered: setDbSize, }, Action{ // Image: "./image//yingyong.png", Text: "设置应用内存", OnTriggered: setServerSize, }, }, }, Menu{ Text: "&帮助", // Image: "./image//bangzhu.png", Items: []MenuItem{ Action{ // Image: "./image//guanyu.png", Text: "关于", OnTriggered: app.aboutactionTriggered, }, /*Action{ // Image: "./image//yaoqiu.png", Text: "要求", OnTriggered: app.aboutactionTriggered, },*/ }, }, }, Children: []Widget{GroupBox{ Title: "基础服务状态", Layout: Grid{Columns: 3}, Children: []Widget{ Label{Text: service1.text, MinSize: Size{Width: 220, Height: 30}, TextColor: walk.RGB(255, 255, 0)}, Label{AssignTo: &service1.labelState, Text: "正在运行", MinSize: Size{Width: 80, Height: 30}}, Composite{ Layout: HBox{}, MaxSize: Size{Width: 198, Height: 30}, Children: []Widget{ PushButton{ AssignTo: &service1.btnRegister, MaxSize: Size{Width: 60, Height: 30}, Text: "注册表", }, PushButton{ AssignTo: &service1.btnStop, MaxSize: Size{Width: 60, Height: 30}, Text: "停止", }, PushButton{ AssignTo: &service1.btnStart, MaxSize: Size{Width: 60, Height: 30}, Text: "启动", }, }, }, }, }, GroupBox{ Title: "业务服务状态", Layout: Grid{Columns: 3}, Children: []Widget{ Label{Text: service3.text, MinSize: Size{Width: 220, Height: 30}}, Label{AssignTo: &service3.labelState, Text: "正在运行", MinSize: Size{Width: 80, Height: 30}}, Composite{ Layout: HBox{}, MaxSize: Size{Width: 198, Height: 30}, Children: []Widget{ PushButton{ AssignTo: &service3.btnRegister, MaxSize: Size{Width: 60, Height: 30}, Text: "注册表", }, PushButton{ AssignTo: &service3.btnStop, MaxSize: Size{Width: 60, Height: 30}, Text: "停止", }, PushButton{ AssignTo: &service3.btnStart, MaxSize: Size{Width: 60, Height: 30}, Text: "启动", }, }, }, }, }, TextEdit{AssignTo: &app.msg, VScroll: true, ReadOnly: true}, Composite{ Layout: HBox{}, Children: []Widget{ PushButton{ MinSize: Size{Width: 200, Height: 30}, Text: "打开windows服务管理程序", OnClicked: openServices, }, HSpacer{}, PushButton{ MinSize: Size{Width: 140, Height: 30}, Text: "关闭本监控窗口", OnClicked: func() { walk.App().Exit(0) }, }, }, }}, OnSizeChanged: func() { _ = app.mw.SetSize(walk.Size(Size{Width: 500, Height: 360})) }, }.Create() winLong := win.GetWindowLong(app.mw.Handle(), win.GWL_STYLE) // 不能调整窗口大小,禁用最大化按钮 win.SetWindowLong(app.mw.Handle(), win.GWL_STYLE, winLong & ^win.WS_SIZEBOX & ^win.WS_MAXIMIZEBOX & ^win.WS_SIZEBOX) // 设置窗体生成在屏幕的正中间,并处理高分屏的情况 // 窗体横坐标 = ( 屏幕宽度 - 窗体宽度 ) / 2 // 窗体纵坐标 = ( 屏幕高度 - 窗体高度 ) / 2 _ = app.mw.SetX((int(win.GetSystemMetrics(0)) - app.mw.Width()) / 2 / app.mw.DPI() * 96) _ = app.mw.SetY((int(win.GetSystemMetrics(1)) - app.mw.Height()) / 2 / app.mw.DPI() * 96) return err } // setServiceState 设置 服务状态描述和按钮状态 func setServiceState(service myService, msg string, btnStartStatus, btnStopStatus, btnRegisterStatus bool) { _ = service.labelState.SetText(msg) service.btnStart.SetEnabled(btnStartStatus) service.btnStop.SetEnabled(btnStopStatus) service.btnRegister.SetEnabled(btnRegisterStatus) } // flushServiceStat 刷新服务状态的协程程序 func flushServiceStat(service myService) { for { winService, err := NewWinService(service.serviceName) if winService == nil || err != nil { if err == windows.ERROR_SERVICE_DOES_NOT_EXIST { setServiceState(service, "未安装", false, false, false) } else { setServiceState(service, "服务打开失败", false, false, true) } } else { if winService.IsStop() { setServiceState(service, "已经停止", true, false, true) } else if winService.IsRunning() { setServiceState(service, "正在运行", false, true, false) } } time.Sleep(time.Second) } } // registerService 【0】注册服务 func registerService(service myService) { if service.serviceName == "GWY20_Mysql" { // 注册 MYSQL 服务 registerWindows(service.serviceName, `SYSTEM\ControlSet001\Services\GWY20_Mysql`, `LocalSystem`, `GWY20_Mysql`, fmt.Sprintf(`%s\mysql\bin\mysqld GWY20_Mysql`, path)) registerWindows(service.serviceName, `SYSTEM\CurrentControlSet\Services\GWY20_Mysql`, `LocalSystem`, `GWY20_Mysql`, fmt.Sprintf(`%s\mysql\bin\mysqld --defaults-file=%s\mysql\my.ini GWY20_Mysql`, path, path)) } else { // 注册 TOMCAT 服务 registerWindows(service.serviceName, `SYSTEM\ControlSet001\Services\GWY20_Tomcat`, `NT Authority\LocalService`, `GWY20_Tomcat`, fmt.Sprintf(`%s\tomcat8\bin\Tomcat8.exe //RS//GWY20_Tomcat`, path)) registerWindows(service.serviceName, `SYSTEM\CurrentControlSet\Services\GWY20_Tomcat`, `NT Authority\LocalService`, `GWY20_Tomcat`, fmt.Sprintf(`%s\tomcat8\bin\Tomcat8.exe //RS//GWY20_Tomcat`, path)) registerJava(service.serviceName, path, 128, 256, 512, 512) registerLog(service.serviceName, path) registerState(service.serviceName, `SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\GWY20_Tomcat\Parameters\Start`, `start`, path) registerState(service.serviceName, `SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\GWY20_Tomcat\Parameters\Stop`, `stop`, path) } showMsg(service.serviceName + " 服务注册成功!") } // startService 启动服务 func startService(service myService) { s, err := NewWinService(service.serviceName) if s == nil || err != nil { return } showMsg(service.serviceName + " 服务开始启动......") err = s.StartService() // time.Sleep(15 * time.Second) if err != nil { showMsg(service.serviceName + " 服务启动失败!") } else { showMsg(service.serviceName + " 服务启动成功。") } } // stopService 停止服务 func stopService(service myService) { s, err := NewWinService(service.serviceName) if s == nil || err != nil { return } showMsg(service.serviceName + " 服务开始停止......") err = s.StopService() if err != nil { showMsg(service.serviceName + " 服务停止失败!") } else { showMsg(service.serviceName + " 服务停止成功。") } } // showMsg 显示内容到 控制面板 func showMsg(msg string) { app.msg.AppendText(time.Now().Format("2006-01-02 15:04:05 ")) app.msg.AppendText(msg) app.msg.AppendText("\r\n") } /* 注册服务部分 */ // registerWindows 【1】修改注册表 func registerWindows(serviceName, regStr, objectName, displayName, imagePath string) { key, exists, _ := registry.CreateKey(registry.LOCAL_MACHINE, regStr, registry.ALL_ACCESS) defer key.Close() // 判断是否已经存在了 if !exists { showMsg(serviceName + " 新建注册表记录!") } _ = key.SetDWordValue(`Type`, uint32(16)) _ = key.SetDWordValue(`Start`, uint32(2)) _ = key.SetDWordValue(`ErrorControl`, uint32(1)) _ = key.SetDWordValue(`WOW64`, uint32(332)) _ = key.SetStringValue(`ObjectName`, objectName) _ = key.SetStringValue(`DisplayName`, displayName) _ = key.SetExpandStringValue(`ImagePath`, imagePath) if serviceName == "GWY20_Tomcat" { _ = key.SetStringValue(`Description`, `Apache Tomcat 8.5.55 Server - https://tomcat.apache.org/`) _ = key.SetStringsValue(`DependOnService`, []string{`Tcpip`, `Afd`}) } key, exists, _ = registry.CreateKey(registry.LOCAL_MACHINE, regStr+`\Parameters`, registry.ALL_ACCESS) defer key.Close() } // registerJava 【2】修改注册表 func registerJava(serviceName, path string, permSize, maxPermSize, xms, xmx int) { key, exists, _ := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\GWY20_Tomcat\Parameters\Java`, registry.ALL_ACCESS) defer key.Close() // 判断是否已经存在了 if !exists { showMsg(serviceName + " Java 新建注册表记录!") } _ = key.SetStringValue(`Jvm`, fmt.Sprintf(`%s\tomcat8/JDK1.8/jre\bin\server\jvm.dll`, path)) _ = key.SetStringsValue(`Options`, []string{ fmt.Sprintf(`-Dcatalina.home=%s\tomcat8`, path), fmt.Sprintf(`-Djava.endorsed.dirs=%s\tomcat8\endorsed`, path), fmt.Sprintf(`-Djava.io.tmpdir=%s\tomcat8\temp`, path), `-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager`, fmt.Sprintf(`-Djava.util.logging.config.file=%s\tomcat8\conf\logging.properties`, path), `-Dfile.encoding=GBK`, fmt.Sprintf(`-XX:PermSize=%dm`, permSize), fmt.Sprintf(`-XX:MaxPermSize=%dm`, maxPermSize), }) _ = key.SetStringValue(`Classpath`, fmt.Sprintf(`%s\tomcat8\bin\bootstrap.jar;%s\tomcat8\bin\tomcat-juli.jar`, path, path)) _ = key.SetDWordValue(`JvmMs`, uint32(xms)) _ = key.SetDWordValue(`JvmMx`, uint32(xmx)) } // registerLog 【3】修改注册表 func registerLog(serviceName, path string) { key, exists, _ := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\GWY20_Tomcat\Parameters\Log`, registry.ALL_ACCESS) defer key.Close() // 判断是否已经存在了 if !exists { showMsg(serviceName + " Log 新建注册表记录!") } _ = key.SetStringValue(`Path`, fmt.Sprintf(`%s\tomcat8\logs`, path)) _ = key.SetStringValue(`StdError`, `auto`) _ = key.SetStringValue(`StdOutput`, `auto`) } // registerState 【4】修改注册表 func registerState(serviceName, regStr, state, path string) { key, exists, _ := registry.CreateKey(registry.LOCAL_MACHINE, regStr, registry.ALL_ACCESS) defer key.Close() // 判断是否已经存在了 if !exists { showMsg(serviceName + " " + state + " 新建注册表记录!") } _ = key.SetStringValue(`Class`, `org.apache.catalina.startup.Bootstrap`) _ = key.SetStringsValue(`Params`, []string{state}) _ = key.SetStringValue(`Mode`, `jvm`) _ = key.SetStringValue(`WorkingPath`, fmt.Sprintf(`%s\tomcat8`, path)) } // Unzip 执行 解压文件操作,目的路径不带本级文件名称 func Unzip(zipFile string, destDir string) error { zipReader, err := zip.OpenReader(zipFile) if err != nil { return err } defer zipReader.Close() for _, f := range zipReader.File { fpath := filepath.Join(destDir, f.Name) if f.FileInfo().IsDir() { _ = os.MkdirAll(fpath, os.ModePerm) } else { return runUnzip(fpath, f) } } return nil } func runUnzip(fpath string, f *zip.File) error { if err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { return err } inFile, err := f.Open() if err != nil { return err } defer inFile.Close() outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } defer outFile.Close() _, err = io.Copy(outFile, inFile) return err } // openServices 打开本地 服务 func openServices() { c := exec.Command("cmd", "/C", "SERVICES.MSC") c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // 不显示命令窗口 if err := c.Start(); err != nil { showMsg(fmt.Sprintf("打开windows服务管理程序失败, 错误信息: %s", err)) } } // clearAll 清除缓存 和 重启服务 func clearAll() { showMsg("执行清除缓存!") stopService(service3) showMsg("正在退出浏览器...") err := exec.Command("cmd.exe", "/c", "taskkill /f /im 360se.exe").Run() if err != nil { showMsg(fmt.Sprintf("退出浏览器发生异常: %s", err.Error())) } showMsg("浏览器退出成功!") showMsg("正在清除浏览器缓存...") _ = os.RemoveAll(fmt.Sprintf(`%s\360se6\User Data`, path)) _ = Unzip(fmt.Sprintf(`%s\tools\User Data.zip`, path), fmt.Sprintf(`%s\360se6`, path)) showMsg("浏览器缓存清除成功!") showMsg("正在清除应用缓存...") _ = os.RemoveAll(fmt.Sprintf(`%s\tomcat8\temp`, path)) _ = os.RemoveAll(fmt.Sprintf(`%s\tomcat8\work\Catalina\localhost\qggwy`, path)) showMsg("应用缓存清除成功!") startService(service3) } // setDbSize 显示设置数据库内存大小界面,等待保存 func setDbSize() { app.RunDbSetingDialog(app.mw, func(setings *DbSetings) { // 停服务 stopService(service1) // 设置修改参数 setDbIni(setings.InnodbBufferPoolSize) // 起服务 startService(service1) showMsg("数据库内存调整完毕!") }) } func setDbIni(innodbBufferPoolSize int) { //读写方式打开文件 myIniFile := fmt.Sprintf(`%s/mysql/my.ini`, path) file, err := os.OpenFile(myIniFile, os.O_RDWR, 0666) if err != nil { showMsg("【异常】打开文件发生错误!" + myIniFile) log.Fatal("打开文件异常:", err) return } //defer关闭文件 defer file.Close() //读取文件内容到io中 reader := bufio.NewReader(file) pos := int64(0) innodbBufferPoolSizeStr := []byte(fmt.Sprintf(`innodb_buffer_pool_size=%dM`, innodbBufferPoolSize)) for { //读取每一行内容 line, err := reader.ReadString('\n') if err != nil { //读到末尾 if err == io.EOF { showMsg("打开读取文件完毕!") break } else { showMsg("【异常】读取文件发生错误:" + line) log.Fatal("读取文件异常:", err) return } } //根据关键词覆盖当前行 if strings.Contains(line, "innodb_buffer_pool_size") { _, _ = file.WriteAt(innodbBufferPoolSizeStr, pos) } //每一行读取完后记录位置 pos += int64(len(line)) } } // setServerSize 显示设置应用内存大小界面,等待保存 func setServerSize() { app.RunAppSetingDialog(app.mw, func(setings *AppSetings) { // 停服务 stopService(service3) // 设置数据库内存大小 //registerJava(service3.serviceName, path, 129, 259, 500, 500) registerJava(service3.serviceName, path, setings.PermSize, setings.MaxPermSize, setings.Xms, setings.Xmx) // 起服务 startService(service3) showMsg("应用内存调整完毕!") }) } // dbBak 数据备份功能 func dbBak() { // 判断 mysql 服务应用启动 if service1.btnStart.Enabled() { walk.MsgBox(app.mw, "错误", "数据库服务未启动,即将进行数据库服务启动!", walk.MsgBoxIconWarning) startService(service1) } time.Sleep(time.Second) // 判断 mysql 服务应用启动 if !service1.btnStart.Enabled() { db, _ := sql.Open("mysql", "root:admin@tcp(127.0.0.1:35017)/hy_qggwy?charset=utf8") showMsg("连接数据库成功!\n备份操作可能需要相当长时间...") // 【压缩data方式】创建临时文件夹 dir := time.Now().Format("2006102150405") if err := os.MkdirAll(dir, os.ModePerm); err != nil { showMsg("创建临时目录时发生异常!\n请重试!") return } // 【sql方式】统计库部分 /* for i := 0; i < len(tableNameTj); i++ { QuerySQL(db, dir, "select * from "+tableNameTj[i], tableNameTj[i], []string{}) }*/ // 【sql方式】基础库部分 /* QuerySQL(db, dir, "select * from a01 where STATUS=1", "a01", []string{"A0155", "JSNLSJ", "TBSJ", "XGSJ"}) for i := 0; i < len(tableName); i++ { QuerySQL(db, dir, "select * from "+tableName[i]+" where a0000 in (select a0000 from a01 where status=1)", tableName[i], []string{}) } QuerySQL(db, dir, "select * from b01", "b01", []string{})*/ // 处理照片信息 copyFileByA57(db, dir) // 关闭服务 stopService(service1) time.Sleep(time.Second) // 备份压缩文件 Zip("./mysql/data", fmt.Sprintf("./%s/data.gz", dir)) dirName := fmt.Sprintf("./%s/", dir) fileName := fmt.Sprintf("%s.gz", dir) // 进行压缩操作 并 删除压缩前目录 Zip(dirName, fileName) if err := os.RemoveAll(dir); err != nil { showMsg("删除历史目录时发生异常!") } time.Sleep(time.Second) // 启动服务 startService(service1) showMsg("已完成数据备份!") showMsg(fmt.Sprintf(`⭐数据备份:%s`, fileName)) } else { showMsg("无法正常启动数据库!") } } // reDbBak 备份数据还原 func reDbBak() { app.RunDbBakSetingDialog(app.mw, func(setings *DbBakSetings) { // 停服务 //stopService(service1) // 起服务 //startService(service1) // 执行还原操作 showMsg("已完成备份数据还原!") }) } //数据库配置结构 type DbSetings struct { InnodbBufferPoolSize int // 数据库缓存大小 } // 运行 数据库设置 Dialog func (mw *myApp) RunDbSetingDialog(owner walk.Form, confirmCall func(*DbSetings)) { var seting *DbSetings var dlg *walk.Dialog var db *walk.DataBinder var acceptPB, cancelPB *walk.PushButton seting = new(DbSetings) // 设置预定值 seting.InnodbBufferPoolSize = 512 _, _ = Dialog{ AssignTo: &dlg, Title: "数据源内存设置", Font: Font{Family: "微软雅黑", PointSize: 9}, DefaultButton: &acceptPB, CancelButton: &cancelPB, DataBinder: DataBinder{ AssignTo: &db, Name: "setings", DataSource: seting, ErrorPresenter: ToolTipErrorPresenter{}, }, MinSize: Size{Width: 450, Height: 160}, Layout: VBox{}, Children: []Widget{ Composite{ Layout: Grid{Columns: 2}, Children: []Widget{ Label{Text: `      数据库内存:`}, NumberEdit{Value: Bind("InnodbBufferPoolSize", Range{Min: 64, Max: 10240}), Suffix: " M", Decimals: 0}, }, }, Composite{ Layout: HBox{}, Children: []Widget{ HSpacer{}, PushButton{ AssignTo: &acceptPB, Text: "保存", OnClicked: func() { if err := db.Submit(); err != nil { showMsg("【异常】处理设置数据库内存时,发生异常!") log.Fatal(err) return } // 关闭页面 dlg.Cancel() // 应用 回调函数 confirmCall(seting) }, }, PushButton{ AssignTo: &cancelPB, Text: "取消", OnClicked: func() { dlg.Cancel() }, }, }, }, }, }.Run(owner) } //应用配置结构 type AppSetings struct { PermSize int // 非堆区初始内存分配大小 MaxPermSize int // 非堆区分配的内存的最大上限 Xms int // 堆区内存初始内存分配的大小 Xmx int // 堆区内存可被分配的最大上限 } // 运行 应用设置 Dialog func (mw *myApp) RunAppSetingDialog(owner walk.Form, confirmCall func(*AppSetings)) { var seting *AppSetings var dlg *walk.Dialog var db *walk.DataBinder var acceptPB, cancelPB *walk.PushButton seting = new(AppSetings) // 设置预定值 seting.PermSize = 128 seting.MaxPermSize = 256 seting.Xmx = 512 seting.Xms = 512 _, _ = Dialog{ AssignTo: &dlg, Title: "应用内存设置", Font: Font{Family: "微软雅黑", PointSize: 9}, DefaultButton: &acceptPB, CancelButton: &cancelPB, DataBinder: DataBinder{ AssignTo: &db, Name: "setings", DataSource: seting, ErrorPresenter: ToolTipErrorPresenter{}, }, MinSize: Size{Width: 450, Height: 270}, Layout: VBox{}, Children: []Widget{ Composite{ Layout: Grid{Columns: 2}, Children: []Widget{ Label{Text: `  PermSize(非堆区)初始内存分配大小:`}, NumberEdit{Value: Bind("PermSize", Range{Min: 64, Max: 10240}), Suffix: " m", Decimals: 0}, Label{Text: `MaxPermSize(非堆区)最大内存分配上限:`}, NumberEdit{Value: Bind("MaxPermSize", Range{Min: 64, Max: 10240}), Suffix: " m", Decimals: 0}, Label{Text: `      Xms(堆区)初始内存分配大小:`}, NumberEdit{Value: Bind("Xms", Range{Min: 64, Max: 10240}), Suffix: " m", Decimals: 0}, Label{Text: `      Xmx(堆区)最大内存分配上限:`}, NumberEdit{Value: Bind("Xmx", Range{Min: 64, Max: 10240}), Suffix: " m", Decimals: 0}, }, }, Composite{ Layout: HBox{}, Children: []Widget{ HSpacer{}, PushButton{ AssignTo: &acceptPB, Text: "保存", OnClicked: func() { if err := db.Submit(); err != nil { showMsg("【异常】处理设置数据库内存时,发生异常!") log.Fatal(err) return } // 关闭页面 dlg.Cancel() // DB 回调函数 confirmCall(seting) }, }, PushButton{ AssignTo: &cancelPB, Text: "取消", OnClicked: func() { dlg.Cancel() }, }, }, }, }, }.Run(owner) } //数据还原设置 type DbBakSetings struct { *walk.MainWindow searchBox *walk.LineEdit path string } // 运行 数据还原设置 Dialog func (mw *myApp) RunDbBakSetingDialog(owner walk.Form, confirmCall func(*DbBakSetings)) { var seting *DbBakSetings var dlg *walk.Dialog var db *walk.DataBinder var acceptPB, cancelPB *walk.PushButton seting = new(DbBakSetings) // 设置预定值 _, _ = Dialog{ AssignTo: &dlg, Title: "数据还原设置", Font: Font{Family: "微软雅黑", PointSize: 9}, DefaultButton: &acceptPB, CancelButton: &cancelPB, DataBinder: DataBinder{ AssignTo: &db, Name: "setings", DataSource: seting, ErrorPresenter: ToolTipErrorPresenter{}, }, MinSize: Size{Width: 450, Height: 220}, Layout: VBox{}, Children: []Widget{ GroupBox{ Layout: HBox{}, Children: []Widget{ LineEdit{ ReadOnly: true, AssignTo: &seting.searchBox, }, PushButton{ Text: "选择", OnClicked: seting.selectFile, }, }, }, Composite{ Layout: HBox{}, Children: []Widget{ HSpacer{}, PushButton{ AssignTo: &acceptPB, Text: "恢复", OnClicked: func() { if err := db.Submit(); err != nil { showMsg("【异常】选择恢复文件时,发生异常!") log.Fatal(err) return } // 关闭页面 dlg.Cancel() // DB 回调函数 confirmCall(seting) }, }, PushButton{ AssignTo: &cancelPB, Text: "取消", OnClicked: func() { dlg.Cancel() }, }, }, }, }, }.Run(owner) } func (mw *DbBakSetings) selectFile() { dlg := new(walk.FileDialog) dlg.Title = "选择还原文件(格式:gz)" dlg.Filter = "可执行文件 (*.gz)|*.gz" mw.searchBox.SetText("") //通过重定向变量设置TextEdit的Text if ok, err := dlg.ShowOpen(mw); err != nil { showMsg("【异常】选择打开文件!") } else if !ok { showMsg("Cancel\n") } mw.searchBox.SetText(mw.path) } // QuerySQL 获取表数据 func QuerySQL(db *sql.DB, dir, sqlStr, tableName string, colNil []string) { rows, _ := db.Query(sqlStr) showMsg(fmt.Sprintf(`开始备份数据:%s;`, tableName)) defer rows.Close() cloumns, _ := rows.Columns() values := make([]sql.RawBytes, len(cloumns)) scanArgs := make([]interface{}, len(values)) for i := range values { scanArgs[i] = &values[i] } aa := fmt.Sprintf("truncate table %s;\n", tableName) for rows.Next() { _ = rows.Scan(scanArgs...) key, value := "(", "(" aa = aa + "insert into " + tableName + " " for i, col := range values { kk := cloumns[i] if inStr(colNil, kk) { continue } if i == len(values)-1 { key = key + kk if value == "(" { if col == nil { value = value + "NULL" } else { value = value + "'" + string(col) + "'" } } else { if col == nil { value = value + ",NULL" } else { value = value + ",'" + string(col) + "'" } } } else { key = key + kk + "," if value == "(" { if col == nil { value = value + "NULL" } else { value = value + "'" + string(col) + "'" } } else { if col == nil { value = value + ",NULL" } else { value = value + ",'" + string(col) + "'" } } } } key = key + ")" value = value + ");\n" aa = aa + key + " values " + value } var path string path = fmt.Sprintf("%s/%s.sql", dir, tableName) file3, _ := os.Create(path) _, _ = file3.WriteString(aa) file3.Close() } // inStr 判断字段关系 func inStr(colNil []string, kk string) bool { for _, s := range colNil { if s == kk { return true } } return false } // copyFileByA57 复制需要备份的照片文件 func copyFileByA57(db *sql.DB, mysqlPath string) { codeValues, _ := db.Query("select concat('tomcat8/HZBPHOTOS/', PHOTOPATH) filePath, PHOTONAME fileName from " + "a57 where a0000 in (select a0000 from a01 where status=1);") //返回所有列 filePath, fileName := "", "" for codeValues.Next() { _ = codeValues.Scan(&filePath, &fileName) if filePath != "" { from := path + "/" + filePath + fileName to := mysqlPath + "/" + filePath _ = os.MkdirAll(to, os.ModePerm) if _, err := CopyFile(from, to+fileName); err != nil { showMsg(fmt.Sprintf(`发现存在照片无法复制:%s`, filePath+fileName)) } } } } // CopyFile 复制文件操作 func CopyFile(src, des string) (w int64, err error) { srcFile, _ := os.Open(src) defer srcFile.Close() desFile, _ := os.Create(des) defer desFile.Close() return io.Copy(desFile, srcFile) } // Zip 打包成zip文件 func Zip(srcDir, zipFileName string) { // 预防:旧文件无法覆盖 _ = os.RemoveAll(zipFileName) // 创建:zip文件 zipfile, _ := os.Create(zipFileName) defer zipfile.Close() // 打开:zip文件 archive := zip.NewWriter(zipfile) defer archive.Close() // 遍历路径信息 _ = filepath.Walk(srcDir, func(path string, info os.FileInfo, _ error) error { // 如果是源路径,提前进行下一个遍历 if path == srcDir { return nil } // 获取:文件头信息 header, _ := zip.FileInfoHeader(info) header.Name = strings.TrimPrefix(path, srcDir+`/`) // 判断:文件是不是文件夹 if info.IsDir() { header.Name += `/` } else { // 设置:zip的文件压缩算法 header.Method = zip.Deflate } // 创建:压缩包头部信息 writer, _ := archive.Encrypt(header.Name, passwordname, zip.AES256Encryption) if !info.IsDir() { file, _ := os.Open(path) defer file.Close() _, _ = io.Copy(writer, file) } return nil }) } // open opens the specified URL in the default browser of the user. func OpenUrl(url string) error { var cmd string var args []string switch runtime.GOOS { case "windows": cmd = "cmd" args = []string{"/c", "start"} case "darwin": cmd = "open" default: // "linux", "freebsd", "openbsd", "netbsd" cmd = "xdg-open" } args = append(args, url) c := exec.Command(cmd, args...) c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} return c.Start() } // HasHzb 判断软件是否安装 func HasHzb() error { key2020, err2020 := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\全国公务员管理信息系统2020版`, registry.QUERY_VALUE) defer key2020.Close() key2021, err2021 := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\全国公务员管理信息系统2021版`, registry.QUERY_VALUE) defer key2021.Close() // 判断是否已经存在了 if err2020 != nil && err2021 != nil { return errors.New("未发现注册软件!") } return nil } // InHzb 判断当前软件是否在正确的位置 func InHzb() error { pwd, _ := os.Getwd() // 判断依据 为是否存在 360se6、tools、Tomcat8 和 mysql 目录下 fileInfoList, _ := ioutil.ReadDir(pwd) if Contains(fileInfoList, "360se6") == -1 || Contains(fileInfoList, "mysql") == -1 || Contains(fileInfoList, "tomcat8") == -1 || Contains(fileInfoList, "tools") == -1 { return errors.New("目录错误") } return nil } // Contains 列表是否包含某值 func Contains(array []fs.FileInfo, val string) (index int) { index = -1 for i := range array { // log.Println(array[i].Name()) //打印当前文件或目录下的文件或目录名 if array[i].Name() == val { index = i return } } return }