电子:ui 和后端进程在 Windows 上访问同一个日志文件
electron: ui and backend processes accessing the same log file on Windows
目标
我的基于电子的应用程序使用 C++ 后端,它保留一个日志文件。我想在我的 Electron 前端页面上显示文件内容。
macOS 版本按预期工作。我只是使用 node.js fs
和 readline
库并即时读取文件,然后将解析后的文本插入 innerHTML。
问题
但是,在 Windows 上,当 CRT fopen
调用使用附加模式“a”时,日志文件似乎被后端锁定。所以 node.js 不断收到异常
EBUSY: resource busy or locked open '/path/to/my.log'
更糟糕的是,我使用第三方库进行日志记录,它的内部并不容易破解。
代码
这是代码的电子端
function OnLoad() {
let logFile = Path.join(__dirname, 'logs', platformDirs[process.platform], 'my.log');
let logElem = document.querySelector('.log');
processLineByLine(logFile, logElem);
}
//
// helpers
//
async function processLineByLine(txtFile, outElement) {
const fileStream = fs.createReadStream(txtFile);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
outElement.innerHTML += line + '<br>';
}
}
这是代码的后端
inline bool OpenLogFile(FILE** ppLogFile) {
TCHAR logPath[MAX_PATH];
DWORD length = GetModuleFileName(NULL, logPath, MAX_PATH);
bool isPathValid = false;
#if (NTDDI_VERSION >= NTDDI_WIN8)
PathCchRemoveFileSpec(logPath, MAX_PATH);
HRESULT resPath = PathCchCombine(logPath, MAX_PATH, logPath, TEXT("my.log"));
isPathValid = (resPath == S_OK);
#else
PathRemoveFileSpec(logPath);
LPWSTR resPath = PathCombine(logPath, logPath, TEXT("my.log"));
isPathValid = (resPath != NULL)
#endif
if (!isPathValid)
return false;
errno_t res = _wfopen_s(ppLogFile, logPath, L"a");
if (res != 0) {
wprintf(TEXT("Error: Failed to open log file: %s"), GetOSErrStr().c_str());
}
return res == 0;
}
问题
这是我的体系结构的固有问题吗?
我是否应该忘记同时从 frontend/backend 个进程访问日志文件?
我考虑过使用消息队列在前端和后端进程之间共享日志,但这会使日志记录更加复杂且容易出错。
有没有简单的方法来获得与 macOS 相同的日志记录体验?
自己解决了。
我必须使用提供更多共享选项的another Win32 API _wfsopen
。
就我而言,以下更改就足够了
*ppLogFile = _wfsopen(logPath, L"a+", _SH_DENYWR);
有帮助。
目标
我的基于电子的应用程序使用 C++ 后端,它保留一个日志文件。我想在我的 Electron 前端页面上显示文件内容。
macOS 版本按预期工作。我只是使用 node.js fs
和 readline
库并即时读取文件,然后将解析后的文本插入 innerHTML。
问题
但是,在 Windows 上,当 CRT fopen
调用使用附加模式“a”时,日志文件似乎被后端锁定。所以 node.js 不断收到异常
EBUSY: resource busy or locked open '/path/to/my.log'
更糟糕的是,我使用第三方库进行日志记录,它的内部并不容易破解。
代码
这是代码的电子端
function OnLoad() {
let logFile = Path.join(__dirname, 'logs', platformDirs[process.platform], 'my.log');
let logElem = document.querySelector('.log');
processLineByLine(logFile, logElem);
}
//
// helpers
//
async function processLineByLine(txtFile, outElement) {
const fileStream = fs.createReadStream(txtFile);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
outElement.innerHTML += line + '<br>';
}
}
这是代码的后端
inline bool OpenLogFile(FILE** ppLogFile) {
TCHAR logPath[MAX_PATH];
DWORD length = GetModuleFileName(NULL, logPath, MAX_PATH);
bool isPathValid = false;
#if (NTDDI_VERSION >= NTDDI_WIN8)
PathCchRemoveFileSpec(logPath, MAX_PATH);
HRESULT resPath = PathCchCombine(logPath, MAX_PATH, logPath, TEXT("my.log"));
isPathValid = (resPath == S_OK);
#else
PathRemoveFileSpec(logPath);
LPWSTR resPath = PathCombine(logPath, logPath, TEXT("my.log"));
isPathValid = (resPath != NULL)
#endif
if (!isPathValid)
return false;
errno_t res = _wfopen_s(ppLogFile, logPath, L"a");
if (res != 0) {
wprintf(TEXT("Error: Failed to open log file: %s"), GetOSErrStr().c_str());
}
return res == 0;
}
问题
这是我的体系结构的固有问题吗? 我是否应该忘记同时从 frontend/backend 个进程访问日志文件? 我考虑过使用消息队列在前端和后端进程之间共享日志,但这会使日志记录更加复杂且容易出错。
有没有简单的方法来获得与 macOS 相同的日志记录体验?
自己解决了。
我必须使用提供更多共享选项的another Win32 API _wfsopen
。
就我而言,以下更改就足够了
*ppLogFile = _wfsopen(logPath, L"a+", _SH_DENYWR);