Merge pull request #1 from xunchahaha/main

11
This commit is contained in:
xuncha
2026-01-31 17:46:20 +08:00
committed by GitHub
4 changed files with 67 additions and 26 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22.12
cache: 'npm'
- name: Install Dependencies
@@ -58,4 +58,4 @@ jobs:
[点击加入 Telegram 群](https://t.me/+hn3QzNc4DbA0MzNl)
EOF
gh release edit "$GITHUB_REF_NAME" --notes-file release_notes.md
gh release edit "$GITHUB_REF_NAME" --notes-file release_notes.md

View File

@@ -43,6 +43,7 @@ export class KeyService {
private GetWindowThreadProcessId: any = null
private IsWindowVisible: any = null
private EnumChildWindows: any = null
private PostMessageW: any = null
private WNDENUMPROC_PTR: any = null
// Advapi32
@@ -57,6 +58,7 @@ export class KeyService {
private readonly HKEY_LOCAL_MACHINE = 0x80000002
private readonly HKEY_CURRENT_USER = 0x80000001
private readonly ERROR_SUCCESS = 0
private readonly WM_CLOSE = 0x0010
private getDllPath(): string {
const isPackaged = typeof app !== 'undefined' && app ? app.isPackaged : process.env.NODE_ENV === 'production'
@@ -224,6 +226,7 @@ export class KeyService {
this.EnumWindows = this.user32.func('EnumWindows', 'bool', [this.WNDENUMPROC_PTR, 'intptr_t'])
this.EnumChildWindows = this.user32.func('EnumChildWindows', 'bool', ['void*', this.WNDENUMPROC_PTR, 'intptr_t'])
this.PostMessageW = this.user32.func('PostMessageW', 'bool', ['void*', 'uint32', 'uintptr_t', 'intptr_t'])
this.GetWindowTextW = this.user32.func('GetWindowTextW', 'int', ['void*', this.koffi.out('uint16*'), 'int'])
this.GetWindowTextLengthW = this.user32.func('GetWindowTextLengthW', 'int', ['void*'])
@@ -437,14 +440,55 @@ export class KeyService {
return fallbackPid ?? null
}
private async killWeChatProcesses() {
private async waitForWeChatExit(timeoutMs = 8000): Promise<boolean> {
const start = Date.now()
while (Date.now() - start < timeoutMs) {
const weixinPid = await this.findPidByImageName('Weixin.exe')
const wechatPid = await this.findPidByImageName('WeChat.exe')
if (!weixinPid && !wechatPid) return true
await new Promise(r => setTimeout(r, 400))
}
return false
}
private async closeWeChatWindows(timeoutMs = 8000): Promise<boolean> {
if (!this.ensureUser32()) return false
let requested = false
const enumWindowsCallback = this.koffi.register((hWnd: any, lParam: any) => {
if (!this.IsWindowVisible(hWnd)) return true
const title = this.getWindowTitle(hWnd)
const className = this.getClassName(hWnd)
const classLower = (className || '').toLowerCase()
const isWeChatWindow = this.isWeChatWindowTitle(title) || classLower.includes('wechat') || classLower.includes('weixin')
if (!isWeChatWindow) return true
requested = true
try {
this.PostMessageW?.(hWnd, this.WM_CLOSE, 0, 0)
} catch { }
return true
}, this.WNDENUMPROC_PTR)
this.EnumWindows(enumWindowsCallback, 0)
this.koffi.unregister(enumWindowsCallback)
if (!requested) return true
return await this.waitForWeChatExit(timeoutMs)
}
private async killWeChatProcesses(): Promise<boolean> {
const gracefulOk = await this.closeWeChatWindows(8000)
if (gracefulOk) return true
try {
await execFileAsync('taskkill', ['/F', '/IM', 'Weixin.exe'])
await execFileAsync('taskkill', ['/F', '/IM', 'WeChat.exe'])
await execFileAsync('taskkill', ['/F', '/T', '/IM', 'Weixin.exe'])
await execFileAsync('taskkill', ['/F', '/T', '/IM', 'WeChat.exe'])
} catch (e) {
// Ignore if not found
}
await new Promise(r => setTimeout(r, 1000))
return await this.waitForWeChatExit(5000)
}
// --- Window Detection ---
@@ -605,15 +649,24 @@ export class KeyService {
}
// 2. Restart WeChat
onStatus?.('正在重启微信以进行获取...', 0)
await this.killWeChatProcesses()
onStatus?.('正在关闭微信以进行获取...', 0)
const closed = await this.killWeChatProcesses()
if (!closed) {
const err = '无法自动关闭微信,请手动退出后重试'
onStatus?.(err, 2)
return { success: false, error: err }
}
// 3. Launch
// 3. Launch
onStatus?.('正在启动微信...', 0)
const sub = spawn(wechatPath, { detached: true, stdio: 'ignore' })
const sub = spawn(wechatPath, {
detached: true,
stdio: 'ignore',
cwd: dirname(wechatPath)
})
sub.unref()
// 4. Wait for Window & Get PID (Crucial change: discover PID from window)
// 4. Wait for Window & Get PID (Crucial change: discover PID from window)
onStatus?.('等待微信界面就绪...', 0)
const pid = await this.waitForWeChatWindow()
if (!pid) {

13
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "weflow",
"version": "1.4.2",
"version": "1.4.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
@@ -9,7 +9,6 @@
"version": "1.4.2",
"hasInstallScript": true,
"dependencies": {
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
"better-sqlite3": "^12.5.0",
"echarts": "^5.5.1",
"echarts-for-react": "^3.0.2",
@@ -1949,16 +1948,6 @@
"node": ">= 10.0.0"
}
},
"node_modules/@nodert-win10-rs4/windows.security.credentials.ui": {
"version": "0.4.4",
"resolved": "https://registry.npmmirror.com/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz",
"integrity": "sha512-P+EsJw5MCQXTxp7mwXfNDvIzIYsB6ple+HNg01QjPWg/PJfAodPuxL6XM7l0sPtYHsDYnfnvoefZMdZRa2Z1ig==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"nan": "latest"
}
},
"node_modules/@npmcli/agent": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/@npmcli/agent/-/agent-3.0.0.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "weflow",
"version": "1.4.2",
"version": "1.4.3",
"description": "WeFlow",
"main": "dist-electron/main.js",
"author": "cc",
@@ -15,7 +15,6 @@
"electron:build": "npm run build"
},
"dependencies": {
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
"better-sqlite3": "^12.5.0",
"echarts": "^5.5.1",
"echarts-for-react": "^3.0.2",
@@ -127,4 +126,4 @@
}
]
}
}
}