forked from go/golangs_learn
VIVIMAN
3 years ago
9 changed files with 434 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||||
|
set GO111MODULE=on |
||||
|
set GOARCH=386 |
||||
|
rsrc -manifest main.manifest -ico serviceMonitor.ico -o rsrc.syso |
||||
|
go build -ldflags="-s -w -H=windowsgui" |
||||
|
upx -9 ./serviceMonitor.exe |
@ -0,0 +1,265 @@ |
|||||
|
// +build windows
|
||||
|
// +build 386
|
||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"github.com/lxn/walk" |
||||
|
. "github.com/lxn/walk/declarative" |
||||
|
"github.com/lxn/win" |
||||
|
"golang.org/x/sys/windows" |
||||
|
"os/exec" |
||||
|
"syscall" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
type myApp struct { |
||||
|
title string |
||||
|
msg *walk.TextEdit |
||||
|
mw *walk.MainWindow |
||||
|
} |
||||
|
|
||||
|
type myService struct { |
||||
|
text string |
||||
|
serviceName string |
||||
|
labelState *walk.Label |
||||
|
btnStart *walk.PushButton |
||||
|
btnStop *walk.PushButton |
||||
|
} |
||||
|
|
||||
|
var app myApp |
||||
|
var service1, service2, service3 myService |
||||
|
|
||||
|
func init() { |
||||
|
app.title = "XXXX管理系统-运行监控" |
||||
|
service1 = myService{ |
||||
|
text: "MySql51(MySql数据库)", |
||||
|
serviceName: "MySql51", |
||||
|
} |
||||
|
service2 = myService{ |
||||
|
text: "Web服务(nginx)", |
||||
|
serviceName: "nginx", |
||||
|
} |
||||
|
service3 = myService{ |
||||
|
text: "XXXX系统", |
||||
|
serviceName: "xxxx-server", |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func main() { |
||||
|
_ = getWindows() |
||||
|
|
||||
|
walk.App().SetProductName(app.title) |
||||
|
walk.App().SetOrganizationName("dwt") |
||||
|
|
||||
|
_ = service1.labelState.SetText("未安装") |
||||
|
_ = service2.labelState.SetText("未安装") |
||||
|
_ = service3.labelState.SetText("未安装") |
||||
|
service1.btnStart.Clicked().Attach(func() { |
||||
|
startService(service1) |
||||
|
}) |
||||
|
service1.btnStop.Clicked().Attach(func() { |
||||
|
stopService(service1) |
||||
|
}) |
||||
|
service2.btnStart.Clicked().Attach(func() { |
||||
|
startService(service2) |
||||
|
}) |
||||
|
service2.btnStop.Clicked().Attach(func() { |
||||
|
stopService(service2) |
||||
|
}) |
||||
|
service3.btnStart.Clicked().Attach(func() { |
||||
|
startService(service3) |
||||
|
}) |
||||
|
service3.btnStop.Clicked().Attach(func() { |
||||
|
stopService(service3) |
||||
|
}) |
||||
|
|
||||
|
go flushServiceStat(service1) |
||||
|
go flushServiceStat(service2) |
||||
|
go flushServiceStat(service3) |
||||
|
|
||||
|
app.mw.Show() |
||||
|
app.mw.Run() |
||||
|
} |
||||
|
|
||||
|
func setServiceState(service myService, msg string, btnStartStatus bool, btnStopStatus bool) { |
||||
|
_ = service.labelState.SetText(msg) |
||||
|
service.btnStart.SetEnabled(btnStartStatus) |
||||
|
service.btnStop.SetEnabled(btnStopStatus) |
||||
|
} |
||||
|
|
||||
|
// 刷新服务状态的协程程序
|
||||
|
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) |
||||
|
} else { |
||||
|
setServiceState(service, "服务打开失败", false, false) |
||||
|
} |
||||
|
} else { |
||||
|
if winService.IsStop() { |
||||
|
setServiceState(service, "已经停止", true, false) |
||||
|
} else if winService.IsRunning() { |
||||
|
setServiceState(service, "正在运行", false, true) |
||||
|
} |
||||
|
} |
||||
|
time.Sleep(time.Second) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 启动服务
|
||||
|
func startService(service myService) { |
||||
|
s, err := NewWinService(service.serviceName) |
||||
|
if s == nil || err != nil { |
||||
|
return |
||||
|
} |
||||
|
showMsg(service.serviceName + " 服务开始启动......") |
||||
|
err = s.StartService() |
||||
|
if err != nil { |
||||
|
showMsg(service.serviceName + " 服务启动失败!") |
||||
|
} else { |
||||
|
showMsg(service.serviceName + " 服务启动成功。") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 停止服务
|
||||
|
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 + " 服务停止成功。") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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") |
||||
|
} |
||||
|
|
||||
|
// 初始始化窗体
|
||||
|
func getWindows() error { |
||||
|
icon, _ := walk.NewIconFromResourceId(3) |
||||
|
err := MainWindow{ |
||||
|
Visible: false, |
||||
|
AssignTo: &app.mw, |
||||
|
Title: app.title, |
||||
|
Size: Size{500, 360}, |
||||
|
Font: Font{Family: "微软雅黑", PointSize: 9}, |
||||
|
Icon: icon, |
||||
|
Layout: VBox{}, |
||||
|
Children: []Widget{ |
||||
|
GroupBox{ |
||||
|
Title: "基础服务状态", |
||||
|
Layout: Grid{Columns: 3}, |
||||
|
Children: []Widget{ |
||||
|
Label{Text: service1.text, MinSize: Size{220, 30}, TextColor: walk.RGB(255, 255, 0)}, |
||||
|
Label{AssignTo: &service1.labelState, Text: "正在运行", MinSize: Size{80, 30}}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
MaxSize: Size{132, 30}, |
||||
|
Children: []Widget{ |
||||
|
PushButton{ |
||||
|
AssignTo: &service1.btnStop, |
||||
|
MaxSize: Size{60, 30}, |
||||
|
Text: "停止", |
||||
|
}, |
||||
|
PushButton{ |
||||
|
AssignTo: &service1.btnStart, |
||||
|
MaxSize: Size{60, 30}, |
||||
|
Text: "启动", |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
Label{Text: service2.text}, |
||||
|
Label{AssignTo: &service2.labelState, Text: "正在运行"}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
MaxSize: Size{132, 30}, |
||||
|
Children: []Widget{ |
||||
|
PushButton{ |
||||
|
AssignTo: &service2.btnStop, |
||||
|
MaxSize: Size{60, 30}, |
||||
|
Text: "停止", |
||||
|
}, |
||||
|
PushButton{ |
||||
|
AssignTo: &service2.btnStart, |
||||
|
MaxSize: Size{60, 30}, |
||||
|
Text: "启动", |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
GroupBox{ |
||||
|
Title: "业务服务状态", |
||||
|
Layout: Grid{Columns: 3}, |
||||
|
Children: []Widget{ |
||||
|
Label{Text: service3.text, MinSize: Size{220, 30}}, |
||||
|
Label{AssignTo: &service3.labelState, Text: "正在运行", MinSize: Size{80, 30}}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
MaxSize: Size{132, 30}, |
||||
|
Children: []Widget{ |
||||
|
PushButton{ |
||||
|
AssignTo: &service3.btnStop, |
||||
|
MaxSize: Size{60, 30}, |
||||
|
Text: "停止", |
||||
|
}, |
||||
|
PushButton{ |
||||
|
AssignTo: &service3.btnStart, |
||||
|
MaxSize: Size{60, 30}, |
||||
|
Text: "启动", |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
TextEdit{AssignTo: &app.msg, VScroll: true, ReadOnly: true}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
Children: []Widget{ |
||||
|
PushButton{ |
||||
|
MinSize: Size{160, 30}, |
||||
|
Text: "打开windows服务管理程序", |
||||
|
OnClicked: func() { |
||||
|
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)) |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
HSpacer{}, |
||||
|
PushButton{ |
||||
|
MinSize: Size{121, 30}, |
||||
|
Text: "关闭本监控窗口", |
||||
|
OnClicked: func() { |
||||
|
walk.App().Exit(0) |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
OnSizeChanged: func() { |
||||
|
_ = app.mw.SetSize(walk.Size(Size{500, 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 |
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> |
||||
|
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/> |
||||
|
<dependency> |
||||
|
<dependentAssembly> |
||||
|
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> |
||||
|
</dependentAssembly> |
||||
|
</dependency> |
||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3"> |
||||
|
<windowsSettings> |
||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> |
||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware> |
||||
|
</windowsSettings> |
||||
|
</application> |
||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> |
||||
|
<security> |
||||
|
<requestedPrivileges> |
||||
|
<requestedExecutionLevel level="requireAdministrator"/> |
||||
|
</requestedPrivileges> |
||||
|
</security> |
||||
|
</trustInfo> |
||||
|
</assembly> |
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -0,0 +1,139 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"github.com/shirou/gopsutil/winservices" |
||||
|
"golang.org/x/sys/windows/svc" |
||||
|
"golang.org/x/sys/windows/svc/mgr" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
// 定义Service对象
|
||||
|
type Service struct { |
||||
|
Name string |
||||
|
srv *winservices.Service |
||||
|
Config mgr.Config |
||||
|
Status winservices.ServiceStatus |
||||
|
} |
||||
|
|
||||
|
// 得到Service信息
|
||||
|
func (s *Service) getServiceDetail() error { |
||||
|
defer func() { |
||||
|
if err := recover(); err != nil { |
||||
|
return |
||||
|
} |
||||
|
}() |
||||
|
err := s.srv.GetServiceDetail() |
||||
|
if err != nil { |
||||
|
// 服务打开失败
|
||||
|
return err |
||||
|
} |
||||
|
s.Name = s.srv.Name |
||||
|
s.Status = s.srv.Status |
||||
|
s.Config = s.srv.Config |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// 启动一个服务
|
||||
|
func (s *Service) StartService() error { |
||||
|
return StartService(s.Name) |
||||
|
} |
||||
|
|
||||
|
// 停止一个服务
|
||||
|
func (s *Service) StopService() error { |
||||
|
return StopService(s.Name) |
||||
|
} |
||||
|
|
||||
|
// 服务是否已经停止
|
||||
|
func (s *Service) IsStop() bool { |
||||
|
return s.Status.State == svc.Stopped |
||||
|
} |
||||
|
|
||||
|
// 服务是否正在运行
|
||||
|
func (s *Service) IsRunning() bool { |
||||
|
return s.Status.State == svc.Running |
||||
|
} |
||||
|
|
||||
|
// 新建一个Service对象
|
||||
|
func NewWinService(serviceName string) (*Service, error) { |
||||
|
winService, err := winservices.NewService(serviceName) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
result := &Service{ |
||||
|
Name: serviceName, |
||||
|
srv: winService, |
||||
|
} |
||||
|
err = result.getServiceDetail() |
||||
|
return result, err |
||||
|
} |
||||
|
|
||||
|
// 得到Service信息
|
||||
|
func GetServiceInfo(serviceName string) (*winservices.Service, error) { |
||||
|
defer func() { |
||||
|
if err := recover(); err != nil { |
||||
|
return |
||||
|
} |
||||
|
}() |
||||
|
newservice, _ := winservices.NewService(serviceName) |
||||
|
err := newservice.GetServiceDetail() |
||||
|
if err != nil { |
||||
|
fmt.Println(serviceName, "服务打开失败!") |
||||
|
return nil, err |
||||
|
} |
||||
|
return newservice, nil |
||||
|
} |
||||
|
|
||||
|
// 启动一个服务
|
||||
|
func StartService(name string) error { |
||||
|
m, err := mgr.Connect() |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
defer m.Disconnect() |
||||
|
s, err := m.OpenService(name) |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("could not access service: %v", err) |
||||
|
} |
||||
|
defer s.Close() |
||||
|
err = s.Start("is", "manual-started") |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("could not start service: %v", err) |
||||
|
} |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// 停止一个服务
|
||||
|
func StopService(name string) error { |
||||
|
return ControlService(name, svc.Stop, svc.Stopped) |
||||
|
} |
||||
|
|
||||
|
// 改一个服务状态,
|
||||
|
func ControlService(name string, c svc.Cmd, to svc.State) error { |
||||
|
m, err := mgr.Connect() |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
defer m.Disconnect() |
||||
|
s, err := m.OpenService(name) |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("could not access service: %v", err) |
||||
|
} |
||||
|
defer s.Close() |
||||
|
status, err := s.Control(c) |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("could not send control=%d: %v", c, err) |
||||
|
} |
||||
|
timeout := time.Now().Add(10 * time.Second) |
||||
|
for status.State != to { |
||||
|
if timeout.Before(time.Now()) { |
||||
|
return fmt.Errorf("timeout waiting for service to go to state=%d", to) |
||||
|
} |
||||
|
time.Sleep(300 * time.Millisecond) |
||||
|
status, err = s.Query() |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("could not retrieve service status: %v", err) |
||||
|
} |
||||
|
} |
||||
|
return nil |
||||
|
} |
Loading…
Reference in new issue