// +build windows package main import ( "bufio" "database/sql" "errors" "fmt" _ "github.com/go-sql-driver/mysql" "github.com/lxn/walk" "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 app myApp var service1, service3 myService var Version = "V2021 1.0.1" // 版本号 var passwordname = "Qw^e1@10&++Hzb...?8" // 解压密码 var path string // 该部分不存在最后 横线 (格式为 D:\hzb2021),使用时需要补充横线 var epsoft1 = `全国公务员管理信息系统2020版` // 系统名称 1 var epsoft2 = `全国公务员管理信息系统2021版` // 系统名称 2 var url = `root:admin@tcp(127.0.0.1:35017)/hy_qggwy?charset=utf8` var tabs Tabs // 清除特殊字符串表和字段 var funcs Funcs // 执行批量操作脚本 var typeStr = `0` // 执行导出名册默认 0-按照职务输出生成 1-按照主职务生成 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 } type tabIdx struct { tabName string // 表名 idxName string // 索引名 idxColumn string // 索引字段 } // 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() { err := GetWindows() if err != nil { walk.MsgBox(app.mw, "错误", "程序初始化错误!", walk.MsgBoxIconWarning) return } 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() } // 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, true) } 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 == service1.serviceName { // 注册 MYSQL 服务 registerWindows(service.serviceName, fmt.Sprintf(`SYSTEM\ControlSet001\Services\%s`, service.serviceName), `LocalSystem`, service.serviceName, fmt.Sprintf(`%s\mysql\bin\mysqld %s`, path, service.serviceName)) registerWindows(service.serviceName, fmt.Sprintf(`SYSTEM\CurrentControlSet\Services\%s`, service.serviceName), `LocalSystem`, service.serviceName, fmt.Sprintf(`%s\mysql\bin\mysqld --defaults-file=%s\mysql\my.ini %s`, path, path, service.serviceName)) } else { // 注册 TOMCAT 服务 registerWindows(service.serviceName, fmt.Sprintf(`SYSTEM\ControlSet001\Services\%s`, service.serviceName), `NT Authority\LocalService`, service.serviceName, fmt.Sprintf(`%s\tomcat8\bin\Tomcat8.exe //RS//%s`, path, service.serviceName)) registerWindows(service.serviceName, fmt.Sprintf(`SYSTEM\CurrentControlSet\Services\%s`, service.serviceName), `NT Authority\LocalService`, service.serviceName, fmt.Sprintf(`%s\tomcat8\bin\Tomcat8.exe //RS//%s`, path, service.serviceName)) registerJava(service.serviceName, path, 128, 256, 512, 512) registerLog(service.serviceName, path) registerState(service.serviceName, fmt.Sprintf(`SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\%s\Parameters\Start`, service.serviceName), `start`, path) registerState(service.serviceName, fmt.Sprintf(`SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\%s\Parameters\Stop`, service.serviceName), `stop`, path) } showMsg(service.serviceName + " 服务注册成功!") if win.IDYES == walk.MsgBox(app.mw, "重启提醒", "注册成功程序,注册信息生效,需要重启电脑!\n是否重启系统...", walk.MsgBoxYesNo) { arg := []string{"-r", "-t", "20"} cmd := exec.Command("shutdown", arg...) _, err := cmd.CombinedOutput() if err != nil { showMsg(" 重启电脑失败,手动重启电脑") } } else { 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 == service3.serviceName { _ = 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, fmt.Sprintf(`SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\%s\Parameters\Java`, serviceName), 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, fmt.Sprintf(`SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\%s\Parameters\Log`, serviceName), 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("应用内存调整完毕!") }) } // 按照职务输出生成(可能人员重复) func getMcByA0281() { typeStr = "0" mc, b := RunMc() if b { return } showMsg("导出文件成功!") showMsg(fmt.Sprintf("存放当前目录下,文件名称:%s", mc)) } // 按照主职务生成(可能人员丢失) func getMcByA0279() { typeStr = "1" mc, b := RunMc() if b { return } showMsg("导出文件成功!") showMsg(fmt.Sprintf("存放当前目录下,文件名称:%s", mc)) } // reDbIndex 重新构建索引 func reDbIndex() { // 判断 mysql 服务应用启动 if service1.btnStart.Enabled() { walk.MsgBox(app.mw, "错误", "数据库服务未启动,即将进行数据库服务启动!", walk.MsgBoxIconWarning) startService(service1) } time.Sleep(time.Second) db, _ := sql.Open("mysql", url) showMsg("连接数据库成功!\n请不要进行其他操作,否则影响执行...") for i := 0; i < len(DbIndex); i++ { ExecSql(db, fmt.Sprintf(`DROP INDEX %s ON %s`, DbIndex[i].idxName, DbIndex[i].tabName)) ExecSql(db, fmt.Sprintf(`ALTER TABLE %s ADD INDEX %s (%s) USING BTREE`, DbIndex[i].tabName, DbIndex[i].idxName, DbIndex[i].idxColumn)) } showMsg("已完成重新构建索引!") } // clearData 数据清洗 (主要同步主细表数据;清洗可录入数据中特殊字符串) func clearData() { // 判断 mysql 服务应用启动 if service1.btnStart.Enabled() { walk.MsgBox(app.mw, "错误", "数据库服务未启动,即将进行数据库服务启动!", walk.MsgBoxIconWarning) startService(service1) } time.Sleep(time.Second) db, _ := sql.Open("mysql", url) showMsg("连接数据库成功!\n请不要进行其他操作,否则影响执行...") for i := range funcs.Sql { sqlStrs := funcs.Sql[i] for _, sqlStr := range sqlStrs.Sql { db.Exec(sqlStr) } showMsg(fmt.Sprintf("已完成%s!", sqlStrs.name)) } for i := range tabs.Tab { tab := tabs.Tab[i] for _, col := range tab.Cols { for i2 := range ts { _, _ = db.Exec(fmt.Sprintf(`update %s set %s=replace(%s, '%s', '') where %s is not null`, tab.name, col, col, ts[i2], col)) } } } showMsg("已完成清洗数据中特殊字符串!") } var ts = []string{ "�", "", "�", "", "&#", } func ExecSql(db *sql.DB, sql string) { stmt, err := db.Prepare(sql) if err != nil { log.Fatal(err) } _, _ = stmt.Exec() defer stmt.Close() } // 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", url) 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) showMsg("程序可能出现【未响应】属于正常!") 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\%s`, fileName, fileName)) } else { showMsg("无法正常启动数据库!") } } // reDbBak 备份数据还原 func reDbBak() { app.RunDbBakSetingDialog(app.mw, func(setings *DbBakSetings) { // 停服务 //stopService(service1) // 起服务 //startService(service1) // 执行还原操作 showMsg("已完成备份数据还原!") }) } 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, fmt.Sprintf(`SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\%s`, epsoft1), registry.QUERY_VALUE) defer key2020.Close() key2021, err2021 := registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf(`SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\%s`, epsoft2), 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 } func (mw *myApp) aboutactionTriggered() { walk.MsgBox(mw.mw, "功能说明", Info, walk.MsgBoxIconQuestion) }