问题:路径含 ( ) & % ! ^ @ 等字符时报"文件路径包含不允许的命令行特殊字符",
(D2-f)、(1) 这类正常业务文件名直接命中。
根因:读取统一入口把路径拼进命令行(cmd.exe /d /c type "..."),为"防炸"在 03d9b8b
引入 ForbiddenPathChars 黑名单——并非业务需求,是实现的自我约束。
实测:真正会坏的只有 %VAR%(必坏) 与延迟展开开启时的 !VAR!,而 ( ) & ^ @ 空格在
双引号内均正常;且 type 是字节透传,这层 cmd 对当初的编码问题毫无帮助。
改动:
- 新增 AnsiFileReader.cs:FileStream + StreamReader(默认 936 解码 + BOM 探测,
与旧 StreamReader 解码路径逐字符等价),不经命令行
- 删除 CommandTypeFileReader.cs 及其 ForbiddenPathChars 字符校验
- 路径只保留"非空"与"文件存在"校验;IO 异常包装为
InvalidOperationException("读取文件失败:{路径}({原因})")并保留 InnerException
- 15 处调用点同步改名;更新 CLAUDE.md 与 Docs 说明
验证:14 个 demo_drl 样例新旧实现字符串/行数逐字符一致;含特殊字符路径(含 %TEMP% 字面
路径,旧实现 rc=1)可读可解析;UTF-8/UTF-16 BOM 结果与旧实现一致;
dotnet build -p:Platform=x86 0 错误且警告集与基线逐条相同。
106 lines
3.2 KiB
C#
106 lines
3.2 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Windows;
|
|
|
|
namespace DrillTools
|
|
{
|
|
/// <summary>
|
|
/// 钻带参数文件选择窗口,列出 A01-A14 文件并以第一行描述文本展示供用户选择。
|
|
/// </summary>
|
|
public partial class DrlParameterSelectionWindow : Window
|
|
{
|
|
/// <summary>
|
|
/// 用户选中的文件完整路径;若取消则为 null。
|
|
/// </summary>
|
|
public string? SelectedFilePath { get; private set; }
|
|
|
|
public DrlParameterSelectionWindow(string paramDirectory)
|
|
{
|
|
InitializeComponent();
|
|
|
|
var items = new List<ParamFileItem>();
|
|
for (int i = 1; i <= 14; i++)
|
|
{
|
|
string fileName = $"A{i:D2}";
|
|
string filePath = Path.Combine(paramDirectory, fileName);
|
|
|
|
if (!File.Exists(filePath))
|
|
continue;
|
|
|
|
string description = ReadFirstLineDescription(filePath);
|
|
items.Add(new ParamFileItem
|
|
{
|
|
FileName = fileName,
|
|
FilePath = filePath,
|
|
Description = $"{fileName} — {description}"
|
|
});
|
|
}
|
|
|
|
FileListBox.ItemsSource = items;
|
|
OkButton.IsEnabled = false;
|
|
|
|
FileListBox.SelectionChanged += (_, _) =>
|
|
{
|
|
OkButton.IsEnabled = FileListBox.SelectedItem != null;
|
|
};
|
|
|
|
FileListBox.MouseDoubleClick += (_, _) =>
|
|
{
|
|
if (FileListBox.SelectedItem is ParamFileItem item)
|
|
{
|
|
SelectedFilePath = item.FilePath;
|
|
DialogResult = true;
|
|
Close();
|
|
}
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 读取参数文件的第一行描述文本(去掉前导分号)。
|
|
/// </summary>
|
|
private static string ReadFirstLineDescription(string filePath)
|
|
{
|
|
try
|
|
{
|
|
string content = AnsiFileReader.ReadAllText(filePath);
|
|
var lines = DrillTapeLineParser.SplitLines(content);
|
|
if (lines.Count > 0)
|
|
{
|
|
string firstLine = lines[0].Text.Trim();
|
|
if (firstLine.StartsWith(";"))
|
|
return firstLine[1..].Trim();
|
|
return firstLine;
|
|
}
|
|
return "(无法读取)";
|
|
}
|
|
catch
|
|
{
|
|
return "(无法读取)";
|
|
}
|
|
}
|
|
|
|
private void OkButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (FileListBox.SelectedItem is ParamFileItem item)
|
|
{
|
|
SelectedFilePath = item.FilePath;
|
|
DialogResult = true;
|
|
Close();
|
|
}
|
|
}
|
|
|
|
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
DialogResult = false;
|
|
Close();
|
|
}
|
|
|
|
private class ParamFileItem
|
|
{
|
|
public string FileName { get; init; } = string.Empty;
|
|
public string FilePath { get; init; } = string.Empty;
|
|
public string Description { get; init; } = string.Empty;
|
|
}
|
|
}
|
|
}
|