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