From 7c113d6e04a041cee7af85cca5a8946101ab8dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Thu, 17 Apr 2025 18:07:07 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shell/base.ts | 5 +-- src/shell/napcat.ts | 34 --------------------- src/shell/pipe.ts | 74 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 src/shell/pipe.ts diff --git a/src/shell/base.ts b/src/shell/base.ts index 9dbd3c74..a8e53b34 100644 --- a/src/shell/base.ts +++ b/src/shell/base.ts @@ -33,7 +33,7 @@ import { NodeIO3MiscListener } from '@/core/listeners/NodeIO3MiscListener'; import { sleep } from '@/common/helper'; import { downloadFFmpegIfNotExists } from '@/common/download-ffmpeg'; import { FFmpegService } from '@/common/ffmpeg'; - +import { connectToNamedPipe } from '@/shell/pipe'; // NapCat Shell App ES 入口文件 async function handleUncaughtExceptions(logger: LogWrapper) { process.on('uncaughtException', (err) => { @@ -313,9 +313,10 @@ export async function NCoreInitShell() { const pathWrapper = new NapCatPathWrapper(); const logger = new LogWrapper(pathWrapper.logsPath); handleUncaughtExceptions(logger); + await connectToNamedPipe(logger).catch(e => logger.logError('命名管道连接失败', e)); downloadFFmpegIfNotExists(logger).then(({ path, reset }) => { if (reset && path) { - FFmpegService.setFfmpegPath(path,logger); + FFmpegService.setFfmpegPath(path, logger); } }).catch(e => { logger.logError('[Ffmpeg] Error:', e); diff --git a/src/shell/napcat.ts b/src/shell/napcat.ts index c3f9bbe8..7b300cb0 100644 --- a/src/shell/napcat.ts +++ b/src/shell/napcat.ts @@ -1,36 +1,2 @@ import { NCoreInitShell } from './base'; -import * as net from 'net'; -import * as process from 'process'; -if (process.platform === 'win32') { - const pid = process.pid; - const pipePath = `\\\\.\\pipe\\NapCat_${pid}`; - try { - const pipeSocket = net.connect(pipePath, () => { - console.log(`已连接到命名管道: ${pipePath}`); - process.stdout.write = ( - chunk: any, - encoding?: BufferEncoding | (() => void), - cb?: () => void - ): boolean => { - if (typeof encoding === 'function') { - cb = encoding; - encoding = undefined; - } - return pipeSocket.write(chunk, encoding as BufferEncoding, cb); - }; - console.log(`stdout 已重定向到命名管道: ${pipePath}`); - }); - - pipeSocket.on('error', (err) => { - console.log(`连接命名管道 ${pipePath} 时出错:`, err); - }); - - pipeSocket.on('end', () => { - console.log('命名管道连接已关闭'); - }); - - } catch (error) { - console.log(`尝试连接命名管道 ${pipePath} 时发生异常:`, error); - } -} NCoreInitShell(); \ No newline at end of file diff --git a/src/shell/pipe.ts b/src/shell/pipe.ts new file mode 100644 index 00000000..bde201cd --- /dev/null +++ b/src/shell/pipe.ts @@ -0,0 +1,74 @@ +import { LogWrapper } from '@/common/log'; +import * as net from 'net'; +import * as process from 'process'; + +/** + * 连接到命名管道并重定向stdout + * @param logger 日志记录器 + * @param timeoutMs 连接超时时间(毫秒),默认5000ms + * @returns Promise,连接成功时resolve,失败时reject + */ +export function connectToNamedPipe(logger: LogWrapper, timeoutMs: number = 5000): Promise<{ disconnect: () => void }> { + return new Promise((resolve, reject) => { + if (process.platform !== 'win32') { + logger.log('只有Windows平台支持命名管道'); + // 非Windows平台不reject,而是返回一个空的disconnect函数 + return resolve({ disconnect: () => { } }); + } + + const pid = process.pid; + const pipePath = `\\\\.\\pipe\\NapCat_${pid}`; + + // 设置连接超时 + const timeoutId = setTimeout(() => { + reject(new Error(`连接命名管道超时: ${pipePath}`)); + }, timeoutMs); + + try { + let originalStdoutWrite = process.stdout.write.bind(process.stdout); + const pipeSocket = net.connect(pipePath, () => { + // 清除超时 + clearTimeout(timeoutId); + + logger.log(`[StdOut] 已重定向到命名管道: ${pipePath}`); + process.stdout.write = ( + chunk: any, + encoding?: BufferEncoding | (() => void), + cb?: () => void + ): boolean => { + if (typeof encoding === 'function') { + cb = encoding; + encoding = undefined; + } + return pipeSocket.write(chunk, encoding as BufferEncoding, cb); + }; + // 提供断开连接的方法 + const disconnect = () => { + process.stdout.write = originalStdoutWrite; + pipeSocket.end(); + logger.log(`已手动断开命名管道连接: ${pipePath}`); + }; + + // 返回成功和断开连接的方法 + resolve({ disconnect }); + }); + + pipeSocket.on('error', (err) => { + clearTimeout(timeoutId); + process.stdout.write = originalStdoutWrite; + logger.log(`连接命名管道 ${pipePath} 时出错:`, err); + reject(err); + }); + + pipeSocket.on('end', () => { + process.stdout.write = originalStdoutWrite; + logger.log('命名管道连接已关闭'); + }); + + } catch (error) { + clearTimeout(timeoutId); + logger.log(`尝试连接命名管道 ${pipePath} 时发生异常:`, error); + reject(error); + } + }); +} \ No newline at end of file