Closed luojunyuan closed 5 years ago
确实没考虑过这个问题……
我想了一下,本身Textractor是支持hook多个进程的,所以其实把所有pid全部记录下来到this.pids
然后把injectProcessByPid改成
private injectProcessByPid () {
this.pids.map((pid) => Hooker.getInstance().injectProcess(pid))
}
就可以都hook到啦。
然后注册退出回调这块,registerProcessExitCallback改成
private registerProcessExitCallback () {
let exitedProcessCount = 0
this.pids.map((pid) => {
registerProcessExitCallback(pid, () => {
exitedProcessCount++
if (exitedProcessCount >= this.pids.length) this.emit('exited', this)
})
})
}
应该就OK。
然后主要就是怎么获取到全部pid的问题,我去看看这个正则表达式怎么写……
还有就是,我这边没有这种一次开好几个进程的游戏……所以要不请你写好测试好后提交个PR?🙏
/"[^"]*"/g
这个正则表达式应该就行,然后取所有 i / 5 %= 1 的匹配项,去掉引号,再parseInt就成啦。
按照你的指示Textractor hook成功了!
yuki:hooker injecting process 704... +23s
yuki:hooker process 704 injected +1ms
yuki:hooker injecting process 13296... +1ms
yuki:hooker process 13296 injected +1ms
yuki:hooker injecting process 13352... +1ms
yuki:hooker process 13352 injected +1ms
yuki:hooker injecting process 3172... +4ms
yuki:hooker process 3172 injected
但是特殊码依旧只是注入了第一个进程,看代码牵扯到ipc层我不知道该如何修改妥当(:з)∠)
yuki:hooker inserting hook /HWN-10@2ABE69:kietasekai.exe to process 704... +5s
yuki:hooker hook /HWN-10@2ABE69:kietasekai.exe inserted into process 704
另外偶尔可能会遇上第一个进程启动了,剩余进程还没启动,导致没能读取完整。。
yuki:game finding pid of KIETASEKAI.EXE... +34ms
yuki:game pid 1 14052 +2s
yuki:game pid 2 undefined +5ms
yuki:game pid 3 undefined +2ms
yuki:game pid 4 undefined
哦这里,去setup\ipc.ts
下,找到
ipcMain.on(
IpcTypes.REQUEST_INSERT_HOOK,
(event: Electron.Event, code: string) => {
if (code !== '') {
Hooker.getInstance().insertHook(runningGame.getPid(), code)
}
}
)
这段,改成
ipcMain.on(
IpcTypes.REQUEST_INSERT_HOOK,
(event: Electron.Event, code: string) => {
if (code !== '') {
// 这里改下Game类的getPid()接口,换成getPids(),返回pids数组
runningGame.getPids().map((pid) => {
Hooker.getInstance().insertHook(pid, code)
})
}
}
)
应该就可以了。
整个启动游戏的流程是这样的:
Main Process TranslatorWindow
+---------------------------------------+ +---------------------------------------+
| | | |
| new Game().start() | | |
| + | | |
| | | | |
| v | Loading | |
| new TranslatorWindow().setGame(Game) +-------------> App.vue::mounted() + |
| | Window... | | |
| +-------------------------------------------+ requestConfig("game") <----+ |
| v | | |
| sendConfig("game") +------------------------------+ |
| | | | |
| | | v |
| +-------------------------------------------+ ipcRenderer request insert hook |
| | | | |
| | | | |
| ipcMain::on(REQUEST_INSERT_HOOK) | | |
| | | |
+---------------------------------------+ +---------------------------------------+
之后我大概会找个时间把整个项目的架构写成Wiki 💪
怎么都解决不掉这bug,其他游戏一切正常,就是多线程的这个
translationManager.ts
public translate (
text: string,
callback: (translation: yuki.Translations['translations']) => void
) {
debug('arrive 1')
let toTranslateCount = 0
for (const key in this.apis) {
if (this.apis[key].isEnable()) {
toTranslateCount++
this.apis[key].translate(text, (translation) => {
//this not work, till game close
debug('[%s] -> %s', this.apis[key].getName(), translation)
callback({
[this.apis[key].getName()]: translation
})
})
}
}
if (toTranslateCount === 0) {
callback({})
}
}
原始语句mecab(日语出得来) 翻译却不显示
关闭游戏后,堆积的翻译一下子涌了出来、并伴有翻译窗口已关闭的error
其他游戏一切正常。。
……看来是个大工程了啊 🥀
我这几天比较忙,6月份之后再着手解决一下好了。
消えた世界と月と少女 这个游戏是吧,我先去搞一个,然后看看能不能把VSCode调试Electron给整起来,这样打断点的话显然能看得更清楚点。
要是你能搞的话,也可以看看怎么把调试模式搭起来,然后在那部分打些断点瞧一瞧(
OK,我搞定了。
具体的原因是发生在Win32.ts中,使用Win32 API注册进程退出的callback时发生的问题。
还是我这部分代码没写好,只考虑到了单进程的情况,一旦一次性注册两个及以上PID就会把整个主进程I/O循环堵死,后面再怎么发IPC请求都收不到了。
解决方案是用类似中间件模式的方式一个一个注册callback,这样就不会阻塞I/O了。
我这边测试通过↓
贴一下特殊码在这边,以防有人搜不到
/HWN-10@2ABE69:kietasekai.exe
另外我也把调试搞起来了,不过有个比较麻烦的问题……因为之前想把所有文件名都改成大写的,结果git搞崩了,现在有可能导致大小写混乱对VSCode的断点识别出现问题,注意一下吧 (¬‿¬)
同样的问题在YUKI-minori-v0.14.3 版本中仍旧出现了。读取了多个task list
我在玩消えた世界と月と少女时游戏会启动四个进程
然后发现每次都是第三个才是应该hook的那个,在parsePidFrom函数下临时补救了一下
有啥更好的通用的处理方法嘛