You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# DLL配置NLog后,C++程序读取日志文件遇共享冲突问题

问题描述

我用C# DLL通过以下代码配置NLog写入日志文件:

private static void SetupLogging()
{
    var Config = new NLog.Config.LoggingConfiguration();
    var logfile = new NLog.Targets.FileTarget("logfile")
    {
        FileName = m_LogFile,
        WriteBom = true,
        Layout = "${longdate}|${level:uppercase=true}|${logger}|${message:withException=true:exceptionSeparator=|}"
    };
    var logconsole = new NLog.Targets.ConsoleTarget("logconsole");

    Config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
    Config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);

    LogManager.Configuration = Config;
}

我的C++应用调用该DLL执行任务,检测到错误时尝试读取日志文件,代码如下:

CFile file{};
CFileException ex{};

if (!file.Open(filePath, CFile::modeRead, &ex))
{
    TCHAR szError[_MAX_PATH]{};
    ex.GetErrorMessage(&szError[0], _MAX_PATH);
    AfxMessageBox(&szError[0], MB_OK | MB_ICONERROR);
    return;
}

此时触发文件共享冲突异常,但弹窗提示期间用记事本可以正常打开日志文件,请问如何解决共享冲突,让C++程序正常读取日志文件?


解决方案

方法1:修改NLog的文件共享设置

NLog的FileTarget默认以独占模式写入文件,导致其他进程无法读取。可以给FileTarget添加FileShare.Read配置,让写入时允许其他进程只读打开文件:

var logfile = new NLog.Targets.FileTarget("logfile")
{
    FileName = m_LogFile,
    WriteBom = true,
    Layout = "${longdate}|${level:uppercase=true}|${logger}|${message:withException=true:exceptionSeparator=|}",
    FileShare = System.IO.FileShare.Read // 新增这一行
};

这样NLog写入日志时的文件共享策略和记事本一致,就能避免冲突。

方法2:修改C++的文件打开模式

如果没法修改C# DLL的代码,可以调整C里CFile::Open的共享参数,允许文件被其他进程写入:
把Open方法的第三个参数(共享模式)改成CFile::shareDenyWrite,这样C
只读打开文件时,只禁止其他进程写入,不影响NLog的写入操作:

if (!file.Open(filePath, CFile::modeRead | CFile::shareDenyWrite, &ex))

也可以用更宽松的CFile::shareReadWrite,允许其他进程同时读写文件:

if (!file.Open(filePath, CFile::modeRead | CFile::shareReadWrite, &ex))

内容的提问来源于stack exchange,提问作者Andrew Truckle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:45:07