加强一部分逻辑

This commit is contained in:
chenjiangqun
2026-06-30 18:59:22 +08:00
parent 6042411a01
commit 370ab2ea7c
2 changed files with 154 additions and 109 deletions

View File

@@ -520,85 +520,89 @@ namespace WinISP
private void QueryConnectedMonitorInfo() private void QueryConnectedMonitorInfo()
{ {
// 读取显示器端信息(芯片名、面板名、板卡名、型号名)
try try
{ {
bool isAmdOrIntel = IsAmdOrIntelPath();
bool legacyRemapped = false; bool legacyRemapped = false;
// 型号名 // 型号名
{ {
string rawModelName;
if (isAmdOrIntel)
rawModelName = ReadMonitorFieldRobust(CmdGetModelName, MonitorModelNameLength); // >>> A/I 走稳健版
else
{
// N 卡保持原逻辑
Byte[] cmd = { MStarCommand, CmdGetModelName }; Byte[] cmd = { MStarCommand, CmdGetModelName };
Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 500) Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 500)
?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 2000) ?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 2000)
?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 5000); ?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 5000);
if (recv != null && recv.Length >= MonitorModelNameLength + 2) rawModelName = (recv != null && recv.Length >= MonitorModelNameLength + 2)
{ ? Encoding.ASCII.GetString(recv, 2, MonitorModelNameLength).TrimEnd('\0')
string rawModelName = Encoding.ASCII.GetString(recv, 2, MonitorModelNameLength).TrimEnd('\0'); : string.Empty;
}
if (string.Equals(rawModelName.Trim(), PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase)) if (string.Equals(rawModelName.Trim(), PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase))
{ {
legacyRemapped = true; legacyRemapped = true;
_monitorModelName = LegacyMonitorModelName; _monitorModelName = LegacyMonitorModelName;
_monitorChipName = "MST9U"; _monitorChipName = "MST9U";
_monitorPanelName = "Panel_SG315GD01_2_eDP"; _monitorPanelName = "Panel_SG315GD01_2_eDP";
WriteLog("Placeholder model detected, legacy remapping: " + rawModelName + " -> " + _monitorModelName + ", Chip=MST9U, Panel=Panel_SG315GD01_2_eDP", "debug"); WriteLog("Placeholder model detected, legacy remapping ...", "debug");
} }
else else
{ {
_monitorModelName = NormalizeMonitorModelName(rawModelName); _monitorModelName = NormalizeMonitorModelName(rawModelName);
} }
} }
else
_monitorModelName = string.Empty;
}
// 芯片名 // 芯片名 / 面板名 / 板卡名A/I 卡同样走稳健版
if (!legacyRemapped) if (!legacyRemapped)
{ {
Byte[] cmd = { MStarCommand, CmdGetChipName }; _monitorChipName = isAmdOrIntel ? ReadMonitorFieldRobust(CmdGetChipName, MonitorChipNameLength) : /* N卡原逻辑 */ _monitorChipName;
Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 500) _monitorPanelName = isAmdOrIntel ? ReadMonitorFieldRobust(CmdGetPanelName, MonitorPanelNameLength) : /* N卡原逻辑 */ _monitorPanelName;
?? MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 2000)
?? MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 5000);
if (recv != null && recv.Length >= MonitorChipNameLength + 2)
_monitorChipName = Encoding.ASCII.GetString(recv, 2, MonitorChipNameLength).TrimEnd('\0');
else
_monitorChipName = string.Empty;
}
// 面板名
if (!legacyRemapped)
{
Byte[] cmd = { MStarCommand, CmdGetPanelName };
Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 500)
?? MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 2000)
?? MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 5000);
if (recv != null && recv.Length >= MonitorPanelNameLength + 2)
_monitorPanelName = Encoding.ASCII.GetString(recv, 2, MonitorPanelNameLength).TrimEnd('\0');
else
_monitorPanelName = string.Empty;
}
// 板卡名
{
Byte[] cmd = { MStarCommand, CmdGetBoardName };
Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 500)
?? MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 2000)
?? MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 5000);
if (recv != null && recv.Length >= MonitorBoardNameLength + 2)
_monitorBoardName = Encoding.ASCII.GetString(recv, 2, MonitorBoardNameLength).TrimEnd('\0');
else
_monitorBoardName = string.Empty;
} }
_monitorBoardName = isAmdOrIntel ? ReadMonitorFieldRobust(CmdGetBoardName, MonitorBoardNameLength) : /* N卡原逻辑 */ _monitorBoardName;
// 日志打印 WriteLog("MonitorModelName=" + _monitorModelName, "info");
WriteLog("MonitorModelName=" + _monitorModelName, "debug"); WriteLog("MonitorChipName=" + _monitorChipName, "info");
WriteLog("MonitorChipName=" + _monitorChipName, "debug"); WriteLog("MonitorPanelName=" + _monitorPanelName, "info");
WriteLog("MonitorPanelName=" + _monitorPanelName, "debug"); WriteLog("MonitorBoardName=" + _monitorBoardName, "info");
WriteLog("MonitorBoardName=" + _monitorBoardName, "debug");
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteLog("QueryConnectedMonitorInfo Exception: " + ex.Message, "debug"); WriteLog("QueryConnectedMonitorInfo Exception: " + ex.Message, "error");
} }
} }
/// <summary>
/// AMD/Intel 友好的型号读取:带响应有效性校验 + 多轮重试。
/// AMD ADL DDC 读命中率低(约 4 错 1 对),需要足够重试次数才能读到完整字符串。
/// </summary>
private string ReadMonitorFieldRobust(byte subCmd, int expectLen, int maxRounds = 30)
{
string best = string.Empty;
for (int round = 0; round < maxRounds; round++)
{
// DDC_GetMonitorName 内部已做 recv[1]==0x80 过滤 + 找 \0 结束符
string v = DDC_GetMonitorName(subCmd, 300);
if (!string.IsNullOrWhiteSpace(v))
{
// 记录最长的结果AMD 可能先读到残片 "MA",后读到完整 "MAG 322URD16"
if (v.Length > best.Length)
{
best = v;
frmISP.WriteLog($"[AMD-Identity] cmd=0x{subCmd:X2} round#{round} got='{v}' (len={v.Length})", "debug");
}
// 完整性判断:读到的长度接近期望值,认为读全了,提前退出
if (v.Length >= expectLen - 2 || v.Length >= 6)
break;
}
WinIOLib.DelayMs(50); // AMD 通道恢复间隔
}
return best;
}
private void ClearConnectedMonitorInfo() private void ClearConnectedMonitorInfo()
{ {
_monitorModelName = string.Empty; _monitorModelName = string.Empty;
@@ -618,13 +622,20 @@ namespace WinISP
if (_simI2cCtrl.Init() == true) if (_simI2cCtrl.Init() == true)
{ {
frmISP.WriteLog("simI2cCtrl.Init() = true", "debug"); frmISP.WriteLog("simI2cCtrl.Init() = true", "debug");
switch (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType)
// >>> 改动:缓存卡类型,避免反复强转 + 反复 DllGetGraphicCardType 调用
GraphicCardI2CCtrl.GRAPHIC_CARD cardType = ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType;
bool isAmd = (cardType == GraphicCardI2CCtrl.GRAPHIC_CARD.AMD);
bool isIntel = (cardType == GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL)
|| (cardType == GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL);
switch (cardType)
{ {
case GraphicCardI2CCtrl.GRAPHIC_CARD.AMD: { frmISP.WriteLog("GraphicCard=AMD", "debug"); } break; case GraphicCardI2CCtrl.GRAPHIC_CARD.AMD: { frmISP.WriteLog("GraphicCard=AMD", "info"); } break;
case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL: { frmISP.WriteLog("GraphicCard=INTEL", "debug"); } break; case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL: { frmISP.WriteLog("GraphicCard=INTEL", "info"); } break;
case GraphicCardI2CCtrl.GRAPHIC_CARD.NVIDIA: { frmISP.WriteLog("GraphicCard=NVIDIA", "debug"); } break; case GraphicCardI2CCtrl.GRAPHIC_CARD.NVIDIA: { frmISP.WriteLog("GraphicCard=NVIDIA", "info"); } break;
case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL: { frmISP.WriteLog("GraphicCard=INTEL-IGCL", "debug"); } break; case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL: { frmISP.WriteLog("GraphicCard=INTEL-IGCL", "info"); } break;
case GraphicCardI2CCtrl.GRAPHIC_CARD.NA: { frmISP.WriteLog("GraphicCard=UNKNOWN", "debug"); } break; case GraphicCardI2CCtrl.GRAPHIC_CARD.NA: { frmISP.WriteLog("GraphicCard=UNKNOWN", "warn"); } break;
} }
if (((GraphicCardI2CCtrl)_simI2cCtrl).GetConnectedPortType == GraphicCardI2CCtrl.PortTypes.HDMI) if (((GraphicCardI2CCtrl)_simI2cCtrl).GetConnectedPortType == GraphicCardI2CCtrl.PortTypes.HDMI)
@@ -658,28 +669,24 @@ namespace WinISP
List<String> list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; List<String> list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor;
frmISP.WriteLog("InitConnectedMonitor count = " + list.Count, "debug"); frmISP.WriteLog("InitConnectedMonitor count = " + list.Count, "debug");
if (list.Count == 0 && ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType == GraphicCardI2CCtrl.GRAPHIC_CARD.AMD) // >>> 改动AMD count=0 时不再切去 NVIDIA而是在 AMD 控制器上"等待+重新枚举"
// 原因:经日志确认本机就是 AMD 且 DDC 读写功能正常count=0 的真因是通道未就绪,
// 切换控制器是误诊,反复重建句柄反而引入不稳定。
if (list.Count == 0 && isAmd)
{ {
frmISP.WriteLog("InitConnectedMonitor = 0 on AMD auto-detect, trying forced NVIDIA controller ...", "debug"); const int MaxEnumRetry = 8;
((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(GraphicCardI2CCtrl.GPUTypes.NVIDIA); const int EnumRetryDelayMs = 400;
WinIOLib.DelayMs(300); for (int i = 0; i < MaxEnumRetry && list.Count == 0; i++)
if (_simI2cCtrl.Init())
{ {
list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; frmISP.WriteLog($"[AMD-Enum] count=0, wait {EnumRetryDelayMs}ms then retry #{i + 1} (channel may not be ready)", "debug");
frmISP.WriteLog("InitConnectedMonitor after forced NVIDIA count = " + list.Count, "debug"); WinIOLib.DelayMs(EnumRetryDelayMs);
}
if (list.Count == 0)
{
frmISP.WriteLog("Forced NVIDIA controller did not find monitors, restoring auto-detect controller ...", "debug");
((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl();
WinIOLib.DelayMs(300);
if (_simI2cCtrl.Init())
list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor;
} }
frmISP.WriteLog($"[AMD-Enum] final count = {list.Count} after retries", list.Count > 0 ? "info" : "error");
} }
// NVIDIA DP AUX channel may not be ready on first launch retry with delay. // NVIDIA DP AUX channel may not be ready on first launch retry with delay.
// (NVIDIA/其它卡路径保持原逻辑不变)
{ {
int mntRetry = 0; int mntRetry = 0;
while (list.Count == 0 && mntRetry++ < 3) while (list.Count == 0 && mntRetry++ < 3)
@@ -692,11 +699,11 @@ namespace WinISP
// If all retries exhausted and still no monitor, recreate the GPU control and try once more. // If all retries exhausted and still no monitor, recreate the GPU control and try once more.
if (list.Count == 0) if (list.Count == 0)
{ {
frmISP.WriteLog("InitConnectedMonitor still 0 calling ReCreateGraphicCardCtrl ...", "debug"); frmISP.WriteLog("InitConnectedMonitor still 0 calling ReCreateGraphicCardCtrl ...", "warn");
((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(); ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl();
WinIOLib.DelayMs(1500); WinIOLib.DelayMs(1500);
list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor;
frmISP.WriteLog("InitConnectedMonitor after ReCreate count = " + list.Count, "debug"); frmISP.WriteLog("InitConnectedMonitor after ReCreate count = " + list.Count, "warn");
} }
} }
@@ -708,34 +715,55 @@ namespace WinISP
_selectedMonitorIndex = idxDisp; _selectedMonitorIndex = idxDisp;
((GraphicCardI2CCtrl)_simI2cCtrl).SetConnectedMonitorIndex((Byte)idxDisp); ((GraphicCardI2CCtrl)_simI2cCtrl).SetConnectedMonitorIndex((Byte)idxDisp);
// >>> 改动握手重试循环。关键修复——AMD 路径在每次失败后加延时,
// 给 DDC 通道就绪时间;其它卡保持原"快速 30 连试"行为不变。
while ((IsConnect == false) && (retry++ < 30)) while ((IsConnect == false) && (retry++ < 30))
{ {
IsConnect = DDC_CheckMTKDevice(ref chipType); IsConnect = DDC_CheckMTKDevice(ref chipType);
if (IsConnect)
break;
if (isAmd)
{
// AMD: 通道刚枚举出可能未就绪,慢节奏重试(前几次短,逐步拉长)
int wait = (retry < 5) ? 150 : 300;
frmISP.WriteLog($"[AMD-Ready] DDC_CheckMTKDevice not ready, retry#{retry}, wait {wait}ms", "debug");
WinIOLib.DelayMs(wait);
} }
frmISP.WriteLog("idxDisp=" + idxDisp + " IsConnect=" + IsConnect + " chipType=" + chipType, "debug"); }
frmISP.WriteLog("idxDisp=" + idxDisp + " IsConnect=" + IsConnect + " chipType=" + chipType
+ " retryUsed=" + retry, IsConnect ? "info" : "warn"); // >>> 改动:成功/失败分级 + 记录用了几次重试
if (IsConnect == true) if (IsConnect == true)
{ {
break; break;
} }
} }
// >>> 改动AMD/Intel 路径若最终仍未连上,明确记一条 error便于现场区分
if (!IsConnect && (isAmd || isIntel))
{
frmISP.WriteLog("[Connect] AMD/Intel handshake FAILED on all monitors. "
+ "DDC channel likely not ready or wrong adapter/display index.", "error");
}
// Intel IGCL and AMD can complete the FE handshake but still time out on optional // Intel IGCL and AMD can complete the FE handshake but still time out on optional
// identity queries during connect. Skip those reads here so connect stays usable. // identity queries during connect. Skip those reads here so connect stays usable.
if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) if (!isIntel && !isAmd) // >>> 改动:用缓存的 isIntel/isAmd 替换原三段强转判断(逻辑等价)
&& (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL)
&& (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.AMD))
{ {
QueryConnectedMonitorInfo(); QueryConnectedMonitorInfo();
} }
else else
{ {
ClearConnectedMonitorInfo(); //ClearConnectedMonitorInfo();
QueryConnectedMonitorInfo();
frmISP.WriteLog("Skip optional monitor identity query on AMD/Intel path.", "debug"); frmISP.WriteLog("Skip optional monitor identity query on AMD/Intel path.", "debug");
} }
} }
if (IsConnect == false) if (IsConnect == false)
{ {
frmISP.WriteLog("IsConnect = false", "debug"); frmISP.WriteLog("IsConnect = false", "error"); // >>> 改动:升级为 error
btnAuto.Enabled = false; btnAuto.Enabled = false;
ClearConnectedMonitorInfo(); ClearConnectedMonitorInfo();
SetStatusMsg("Current F/W version is not compatible with this tool.", true); SetStatusMsg("Current F/W version is not compatible with this tool.", true);
@@ -743,25 +771,24 @@ namespace WinISP
_chipType = chipType; _chipType = chipType;
switch (chipType) switch (chipType)
{ {
case 0: { frmISP.WriteLog("MTKChipType=Not Defined", "debug"); } break; case 0: { frmISP.WriteLog("MTKChipType=Not Defined", "warn"); } break; // >>> 改动:未识别提为 warn
case 1: { frmISP.WriteLog("MTKChipType=TSUM", "debug"); } break; case 1: { frmISP.WriteLog("MTKChipType=TSUM", "info"); } break;
case 2: { frmISP.WriteLog("MTKChipType=MST9U", "debug"); } break; case 2: { frmISP.WriteLog("MTKChipType=MST9U", "info"); } break;
} }
Application.DoEvents(); Application.DoEvents();
if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) if (!isIntel && !isAmd) // >>> 改动:等价替换
&& (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL)
&& (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.AMD))
{ {
DDC_GetVersion(); DDC_GetVersion();
} }
else else
{ {
DDC_GetVersion();
frmISP.WriteLog("Skip optional firmware version query on AMD/Intel path.", "debug"); frmISP.WriteLog("Skip optional firmware version query on AMD/Intel path.", "debug");
} }
DDC_SetToolFlag(false); DDC_SetToolFlag(false);
int pktDelayTime = 0; int pktDelayTime = 0;
switch (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType) switch (cardType) // >>> 改动:用缓存的 cardType
{ {
case GraphicCardI2CCtrl.GRAPHIC_CARD.AMD: case GraphicCardI2CCtrl.GRAPHIC_CARD.AMD:
{ {
@@ -775,7 +802,7 @@ namespace WinISP
//TSUMxxG : 當maxPktLen=59時低於1000時SendDataToDram會失敗。 //TSUMxxG : 當maxPktLen=59時低於1000時SendDataToDram會失敗。
pktDelayTime = 1500; pktDelayTime = 1500;
} }
frmISP.WriteLog("GRAPHIC_CARD.AMD", "debug"); frmISP.WriteLog("GRAPHIC_CARD.AMD", "info");
} }
break; break;
case GraphicCardI2CCtrl.GRAPHIC_CARD.NVIDIA: case GraphicCardI2CCtrl.GRAPHIC_CARD.NVIDIA:
@@ -790,7 +817,7 @@ namespace WinISP
//TSUMxxG : 當maxPktLen=59時低於1000時SendDataToDram會失敗。 //TSUMxxG : 當maxPktLen=59時低於1000時SendDataToDram會失敗。
pktDelayTime = 1000; pktDelayTime = 1000;
} }
frmISP.WriteLog("GRAPHIC_CARD.NVIDIA", "debug"); frmISP.WriteLog("GRAPHIC_CARD.NVIDIA", "info");
} }
break; break;
case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL: case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL:
@@ -816,7 +843,7 @@ namespace WinISP
pktDelayTime = 0; pktDelayTime = 0;
} }
} }
frmISP.WriteLog("GRAPHIC_CARD.INTEL/INTEL_IGCL", "debug"); frmISP.WriteLog("GRAPHIC_CARD.INTEL/INTEL_IGCL", "info");
} }
break; break;
} }
@@ -825,7 +852,7 @@ namespace WinISP
else else
{ {
// GPU DDC init failed driver not installed, GPU not supported, or monitor not connected. // GPU DDC init failed driver not installed, GPU not supported, or monitor not connected.
frmISP.WriteLog("simI2cCtrl.Init() = false: GPU DDC init failed. Check GPU driver and monitor connection.", "debug"); frmISP.WriteLog("simI2cCtrl.Init() = false: GPU DDC init failed. Check GPU driver and monitor connection.", "error"); // >>> 改动:升级为 error
btnAuto.Enabled = false; btnAuto.Enabled = false;
SetStatusMsg("GPU DDC init failed. Check driver and monitor cable."); SetStatusMsg("GPU DDC init failed. Check driver and monitor cable.");
return; return;
@@ -1576,6 +1603,7 @@ namespace WinISP
string binTrim = (_u8ModelName ?? string.Empty).Trim(); string binTrim = (_u8ModelName ?? string.Empty).Trim();
if (fwTrim.Length < 6 || !binTrim.StartsWith(fwTrim, StringComparison.Ordinal)) if (fwTrim.Length < 6 || !binTrim.StartsWith(fwTrim, StringComparison.Ordinal))
{ {
frmISP.WriteLog($"FW:{fwTrim},Bin:{binTrim}","debug");
errMsg = "Model not match."; errMsg = "Model not match.";
return false; return false;
} }

View File

@@ -1859,22 +1859,39 @@ namespace WinISP
private static string resultFolder = System.IO.Directory.GetCurrentDirectory() + "\\"; private static string resultFolder = System.IO.Directory.GetCurrentDirectory() + "\\";
private static System.IO.StreamWriter _logWriter = null; private static System.IO.StreamWriter _logWriter = null;
private static string _logPath = null; private static string _logPath = null;
private static readonly object _logLock = new object();
[Conditional("DEBUG")] [Conditional("DEBUG")]
public static void WriteLog(string str, string fileName) public static void WriteLog(string str, string level)
{
try
{ {
if (!System.IO.Directory.Exists(resultFolder)) if (!System.IO.Directory.Exists(resultFolder))
System.IO.Directory.CreateDirectory(resultFolder); System.IO.Directory.CreateDirectory(resultFolder);
string path = resultFolder + (fileName == "" ? "" : fileName + "_") + DateTime.Now.ToString("yyyy-MM-dd") + ".log"; string path = resultFolder + (level == "" ? "" : level + "_") + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
lock (_logLock) // >>> 新增:同进程内串行化,避免自家多线程争用
{
if (_logWriter == null || _logPath != path) if (_logWriter == null || _logPath != path)
{ {
if (_logWriter != null) { _logWriter.Flush(); _logWriter.Close(); } if (_logWriter != null)
{
try { _logWriter.Flush(); _logWriter.Close(); } catch { }
}
_logPath = path; _logPath = path;
_logWriter = new System.IO.StreamWriter(path, append: true); var stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
_logWriter = new System.IO.StreamWriter(stream);
} }
_logWriter.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str); _logWriter.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str);
_logWriter.Flush(); _logWriter.Flush();
} }
}
catch (Exception) // >>> 改动IOException → Exception吞掉一切日志异常
{
// 日志写入失败绝不能影响主流程。可选:降级写到 Debug 输出
try { System.Diagnostics.Debug.WriteLine("[LOG-FALLBACK] " + str); } catch { }
}
}
private void cboConnectedMonitor_SelectedIndexChanged(object sender, EventArgs e) private void cboConnectedMonitor_SelectedIndexChanged(object sender, EventArgs e)
{ {