电子:ui 和后端进程在 Windows 上访问同一个日志文件

electron: ui and backend processes accessing the same log file on Windows

目标

我的基于电子的应用程序使用 C++ 后端,它保留一个日志文件。我想在我的 Electron 前端页面上显示文件内容。

macOS 版本按预期工作。我只是使用 node.js fsreadline 库并即时读取文件,然后将解析后的文本插入 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);

有帮助。