mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 22.12
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
@@ -58,4 +58,4 @@ jobs:
|
|||||||
[点击加入 Telegram 群](https://t.me/+hn3QzNc4DbA0MzNl)
|
[点击加入 Telegram 群](https://t.me/+hn3QzNc4DbA0MzNl)
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
gh release edit "$GITHUB_REF_NAME" --notes-file release_notes.md
|
gh release edit "$GITHUB_REF_NAME" --notes-file release_notes.md
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export class KeyService {
|
|||||||
private GetWindowThreadProcessId: any = null
|
private GetWindowThreadProcessId: any = null
|
||||||
private IsWindowVisible: any = null
|
private IsWindowVisible: any = null
|
||||||
private EnumChildWindows: any = null
|
private EnumChildWindows: any = null
|
||||||
|
private PostMessageW: any = null
|
||||||
private WNDENUMPROC_PTR: any = null
|
private WNDENUMPROC_PTR: any = null
|
||||||
|
|
||||||
// Advapi32
|
// Advapi32
|
||||||
@@ -57,6 +58,7 @@ export class KeyService {
|
|||||||
private readonly HKEY_LOCAL_MACHINE = 0x80000002
|
private readonly HKEY_LOCAL_MACHINE = 0x80000002
|
||||||
private readonly HKEY_CURRENT_USER = 0x80000001
|
private readonly HKEY_CURRENT_USER = 0x80000001
|
||||||
private readonly ERROR_SUCCESS = 0
|
private readonly ERROR_SUCCESS = 0
|
||||||
|
private readonly WM_CLOSE = 0x0010
|
||||||
|
|
||||||
private getDllPath(): string {
|
private getDllPath(): string {
|
||||||
const isPackaged = typeof app !== 'undefined' && app ? app.isPackaged : process.env.NODE_ENV === 'production'
|
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.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.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.GetWindowTextW = this.user32.func('GetWindowTextW', 'int', ['void*', this.koffi.out('uint16*'), 'int'])
|
||||||
this.GetWindowTextLengthW = this.user32.func('GetWindowTextLengthW', 'int', ['void*'])
|
this.GetWindowTextLengthW = this.user32.func('GetWindowTextLengthW', 'int', ['void*'])
|
||||||
@@ -437,14 +440,55 @@ export class KeyService {
|
|||||||
return fallbackPid ?? null
|
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 {
|
try {
|
||||||
await execFileAsync('taskkill', ['/F', '/IM', 'Weixin.exe'])
|
await execFileAsync('taskkill', ['/F', '/T', '/IM', 'Weixin.exe'])
|
||||||
await execFileAsync('taskkill', ['/F', '/IM', 'WeChat.exe'])
|
await execFileAsync('taskkill', ['/F', '/T', '/IM', 'WeChat.exe'])
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Ignore if not found
|
// Ignore if not found
|
||||||
}
|
}
|
||||||
await new Promise(r => setTimeout(r, 1000))
|
|
||||||
|
return await this.waitForWeChatExit(5000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Window Detection ---
|
// --- Window Detection ---
|
||||||
@@ -605,15 +649,24 @@ export class KeyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Restart WeChat
|
// 2. Restart WeChat
|
||||||
onStatus?.('正在重启微信以进行获取...', 0)
|
onStatus?.('正在关闭微信以进行获取...', 0)
|
||||||
await this.killWeChatProcesses()
|
const closed = await this.killWeChatProcesses()
|
||||||
|
if (!closed) {
|
||||||
|
const err = '无法自动关闭微信,请手动退出后重试'
|
||||||
|
onStatus?.(err, 2)
|
||||||
|
return { success: false, error: err }
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Launch
|
// 3. Launch
|
||||||
onStatus?.('正在启动微信...', 0)
|
onStatus?.('正在启动微信...', 0)
|
||||||
const sub = spawn(wechatPath, { detached: true, stdio: 'ignore' })
|
const sub = spawn(wechatPath, {
|
||||||
|
detached: true,
|
||||||
|
stdio: 'ignore',
|
||||||
|
cwd: dirname(wechatPath)
|
||||||
|
})
|
||||||
sub.unref()
|
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)
|
onStatus?.('等待微信界面就绪...', 0)
|
||||||
const pid = await this.waitForWeChatWindow()
|
const pid = await this.waitForWeChatWindow()
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
|
|||||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "weflow",
|
"name": "weflow",
|
||||||
"version": "1.4.2",
|
"version": "1.4.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
|
|
||||||
"better-sqlite3": "^12.5.0",
|
"better-sqlite3": "^12.5.0",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"echarts-for-react": "^3.0.2",
|
"echarts-for-react": "^3.0.2",
|
||||||
@@ -1949,16 +1948,6 @@
|
|||||||
"node": ">= 10.0.0"
|
"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": {
|
"node_modules/@npmcli/agent": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@npmcli/agent/-/agent-3.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@npmcli/agent/-/agent-3.0.0.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "weflow",
|
"name": "weflow",
|
||||||
"version": "1.4.2",
|
"version": "1.4.3",
|
||||||
"description": "WeFlow",
|
"description": "WeFlow",
|
||||||
"main": "dist-electron/main.js",
|
"main": "dist-electron/main.js",
|
||||||
"author": "cc",
|
"author": "cc",
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
"electron:build": "npm run build"
|
"electron:build": "npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
|
|
||||||
"better-sqlite3": "^12.5.0",
|
"better-sqlite3": "^12.5.0",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"echarts-for-react": "^3.0.2",
|
"echarts-for-react": "^3.0.2",
|
||||||
@@ -127,4 +126,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user