x
This commit is contained in:
101
internal/wechat/process/windows/detector.go
Normal file
101
internal/wechat/process/windows/detector.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/sjzar/chatlog/internal/wechat/model"
|
||||
"github.com/sjzar/chatlog/pkg/appver"
|
||||
)
|
||||
|
||||
const (
|
||||
V3ProcessName = "WeChat"
|
||||
V4ProcessName = "Weixin"
|
||||
V3DBFile = "Msg\\Misc.db"
|
||||
V4DBFile = "db_storage\\message\\message_0.db"
|
||||
)
|
||||
|
||||
// Detector 实现 Windows 平台的进程检测器
|
||||
type Detector struct{}
|
||||
|
||||
// NewDetector 创建一个新的 Windows 检测器
|
||||
func NewDetector() *Detector {
|
||||
return &Detector{}
|
||||
}
|
||||
|
||||
// FindProcesses 查找所有微信进程并返回它们的信息
|
||||
func (d *Detector) FindProcesses() ([]*model.Process, error) {
|
||||
processes, err := process.Processes()
|
||||
if err != nil {
|
||||
log.Errorf("获取进程列表失败: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []*model.Process
|
||||
for _, p := range processes {
|
||||
name, err := p.Name()
|
||||
name = strings.TrimSuffix(name, ".exe")
|
||||
if err != nil || (name != V3ProcessName && name != V4ProcessName) {
|
||||
continue
|
||||
}
|
||||
|
||||
// v4 存在同名进程,需要继续判断 cmdline
|
||||
if name == V4ProcessName {
|
||||
cmdline, err := p.Cmdline()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
if strings.Contains(cmdline, "--") {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// 获取进程信息
|
||||
procInfo, err := d.getProcessInfo(p)
|
||||
if err != nil {
|
||||
log.Errorf("获取进程 %d 的信息失败: %v", p.Pid, err)
|
||||
continue
|
||||
}
|
||||
|
||||
result = append(result, procInfo)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getProcessInfo 获取微信进程的详细信息
|
||||
func (d *Detector) getProcessInfo(p *process.Process) (*model.Process, error) {
|
||||
procInfo := &model.Process{
|
||||
PID: uint32(p.Pid),
|
||||
Status: model.StatusOffline,
|
||||
Platform: model.PlatformWindows,
|
||||
}
|
||||
|
||||
// 获取可执行文件路径
|
||||
exePath, err := p.Exe()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
procInfo.ExePath = exePath
|
||||
|
||||
// 获取版本信息
|
||||
versionInfo, err := appver.New(exePath)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
procInfo.Version = versionInfo.Version
|
||||
procInfo.FullVersion = versionInfo.FullVersion
|
||||
|
||||
// 初始化附加信息(数据目录、账户名)
|
||||
if err := initializeProcessInfo(p, procInfo); err != nil {
|
||||
log.Errorf("初始化进程信息失败: %v", err)
|
||||
// 即使初始化失败也返回部分信息
|
||||
}
|
||||
|
||||
return procInfo, nil
|
||||
}
|
||||
12
internal/wechat/process/windows/detector_others.go
Normal file
12
internal/wechat/process/windows/detector_others.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !windows
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
"github.com/sjzar/chatlog/internal/wechat/model"
|
||||
)
|
||||
|
||||
func initializeProcessInfo(p *process.Process, info *model.Process) error {
|
||||
return nil
|
||||
}
|
||||
48
internal/wechat/process/windows/detector_windows.go
Normal file
48
internal/wechat/process/windows/detector_windows.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/sjzar/chatlog/internal/wechat/model"
|
||||
)
|
||||
|
||||
// initializeProcessInfo 获取进程的数据目录和账户名
|
||||
func initializeProcessInfo(p *process.Process, info *model.Process) error {
|
||||
files, err := p.OpenFiles()
|
||||
if err != nil {
|
||||
log.Error("获取打开文件列表失败: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
dbPath := V3DBFile
|
||||
if info.Version == 4 {
|
||||
dbPath = V4DBFile
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
if strings.HasSuffix(f.Path, dbPath) {
|
||||
filePath := f.Path[4:] // 移除 "\\?\" 前缀
|
||||
parts := strings.Split(filePath, string(filepath.Separator))
|
||||
if len(parts) < 4 {
|
||||
log.Debug("无效的文件路径格式: " + filePath)
|
||||
continue
|
||||
}
|
||||
|
||||
info.Status = model.StatusOnline
|
||||
if info.Version == 4 {
|
||||
info.DataDir = strings.Join(parts[:len(parts)-3], string(filepath.Separator))
|
||||
info.AccountName = parts[len(parts)-4]
|
||||
} else {
|
||||
info.DataDir = strings.Join(parts[:len(parts)-2], string(filepath.Separator))
|
||||
info.AccountName = parts[len(parts)-3]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user