+ 实现基础 web 服务,提供 /ping、/list、/stop 路由

This commit is contained in:
2024-07-03 23:39:17 +08:00
parent a5688e3426
commit 245fba4ed0
7 changed files with 422 additions and 0 deletions

39
src/main.go Normal file
View File

@@ -0,0 +1,39 @@
package main
import (
"fmt"
"net"
"os"
)
func main() {
// p := listProcess("kugou")
// for _, ps := range p {
// fmt.Println(ps.Pid, ps.Name)
// }
s := Service{
Port: 12340,
}
s.Run()
}
// 获取本机 IP 地址
func GetLocalIP() []string {
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
ip := []string{}
for _, address := range addrs {
// 检查ip地址判断是否回环地址
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
ip = append(ip, ipnet.IP.String())
}
}
}
return ip
}

34
src/main.http Normal file
View File

@@ -0,0 +1,34 @@
@url=http://localhost:12340
@accept=Accept: application/json
@content-type=Content-Type: application/json
###
GET {{url}}/ping
{{accept}}
###
GET {{url}}/list
{{accept}}
###
GET {{url}}/list?name=notepad
{{accept}}
###
GET {{url}}/listps
{{accept}}
###
GET {{url}}/listps?name=Notepad
{{accept}}
###
POST {{url}}/stop
{{accept}}
{{content-type}}
{
"Id": 4900,
"ProcessName": "Taskmgr"
}

89
src/proc.go Normal file
View File

@@ -0,0 +1,89 @@
package main
import (
"encoding/json"
"fmt"
"os/exec"
"strings"
"github.com/shirou/gopsutil/v4/process"
"golang.org/x/text/encoding/simplifiedchinese"
)
type Process struct {
Pid int32 `json:"Id"`
Name string `json:"ProcessName"`
Exe string `json:"Path"`
Title string `json:"MainWindowTitle"`
}
func ListProcess(filter string) []Process {
ps := []Process{}
v, _ := process.Processes()
for _, value := range v {
name, _ := value.Name()
exe, _ := value.Exe()
if name == "" {
continue
}
if value.Pid <= 10 {
continue
}
if strings.Contains(exe, "C:\\Windows") {
continue
}
if !strings.Contains(strings.ToLower(name), strings.ToLower(filter)) {
continue
}
title := GetMainWindowTitle(value.Pid)
p := Process{
Pid: value.Pid,
Name: name,
Exe: exe,
Title: title,
}
ps = append(ps, p)
}
return ps
}
// TODO filter 参数还有一些问题,无法获取
func ListProcessesUsingPowerShell(filter string) []Process {
ps := []Process{}
command := fmt.Sprintf("Get-Process *%s* | Where-Object {$_.MainWindowTitle} | Select-Object -Property Id,ProcessName,MainWindowTitle,Path | ConvertTo-Json -Compress ", filter)
fmt.Println(command)
result := exec.Command("powershell", "-Command", command)
output, _ := result.CombinedOutput()
// str := ConvertByte2String(output, "GB18030")
b, _ := simplifiedchinese.GB18030.NewDecoder().Bytes(output)
err := json.Unmarshal(b, &ps)
if err != nil {
println(err)
}
return ps
}
func StopProcess(pid int32) (Process, error) {
p, err := process.NewProcess(pid)
if err != nil {
return Process{}, err
}
name, _ := p.Name()
exe, _ := p.Exe()
ps := Process{
Pid: p.Pid,
Name: name,
Exe: exe,
}
err = p.Terminate()
if err != nil {
return ps, err
}
return ps, nil
}

74
src/services.go Normal file
View File

@@ -0,0 +1,74 @@
package main
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type Service struct {
Port int
}
func (s Service) Run() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
// 重定向到 /ping
c.Redirect(http.StatusMovedPermanently, "/ping")
})
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"code": 0,
"data": gin.H{
"message": "pong",
},
})
})
r.GET("/list", func(c *gin.Context) {
name := c.Query("name")
ps := ListProcess(name)
c.JSON(http.StatusOK, gin.H{
"code": 0,
"data": ps,
})
})
r.GET("/listps", func(c *gin.Context) {
name := c.Query("name")
ps := ListProcessesUsingPowerShell(name)
c.JSON(http.StatusOK, gin.H{
"code": 0,
"data": ps,
})
})
r.POST("/stop", func(c *gin.Context) {
var p Process
if err := c.ShouldBindJSON(&p); err == nil {
ps, err := StopProcess(p.Pid)
if err == nil {
c.JSON(http.StatusOK, gin.H{
"code": 0,
"data": gin.H{
"message": "A termination signal has been sent",
"process": ps,
},
})
} else {
c.JSON(http.StatusBadRequest, gin.H{
"code": 1,
"data": gin.H{
"message": "An unknown error occurred, see error for details",
"error": err.Error(),
},
})
}
}
})
r.Run(":" + strconv.Itoa(s.Port))
}

34
src/windowtitle.go Normal file
View File

@@ -0,0 +1,34 @@
package main
import (
"os/exec"
"strconv"
"strings"
"golang.org/x/text/encoding/simplifiedchinese"
)
func GetMainWindowTitle(pid int32) string {
id := strconv.Itoa(int(pid))
command := "Get-Process -PID " + id + " | Format-List -Property MainWindowTitle"
cmd := exec.Command("powershell.exe", "-command", command)
output, _ := cmd.CombinedOutput()
str := ConvertByte2String(output, "GB18030")
str = strings.ReplaceAll(str, "\r\n", "")
str = strings.ReplaceAll(str, "MainWindowTitle : ", "")
return str
}
func ConvertByte2String(byte []byte, charset string) string {
var str string
switch charset {
case "GB18030":
var decodeBytes, _ = simplifiedchinese.GB18030.NewDecoder().Bytes(byte)
str = string(decodeBytes)
case "UTF8":
fallthrough
default:
str = string(byte)
}
return str
}