b75439c以"命令行是多余的"为由把读取改成 FileStream+StreamReader,是错误前提: 项目存在无法用标准文件 I/O 读取的加密 txt/钻带文件(CLAUDE.md "Encrypted file reading"、 Docs/readme.md "读取加密钻带(使用cmd命令type读取)"、 Docs/刀具列表拖动排序功能说明.md "加密文件:使用 cmd 命令读取"均有记录), 该改动会导致这些文件读取失败。本次回退。 改动: - 还原 CommandTypeFileReader.cs:cmd.exe /d /c type(ANSI/936 解码), 失败时退出码与 stderr 保留在异常消息里 - 删除 ForbiddenPathChars 与两处字符校验(本次报错根因): ( ) & ^ @ 空格在双引号内对 type 安全,黑名单只会误伤 (D2-f)、(1) 等正常文件名 - 保留"非空路径""文件存在"校验与 ReadAllText(path, encoding) 重载 - 删除 AnsiFileReader.cs,15 处调用点改回 - CLAUDE.md / .trellis/spec/:恢复"加密文件必须用 cmd type"的说明, 并标注为不可优化掉的硬约束(含b75439c反例) 验证:demo_drl 全部 36 个文件与2335894实现逐字符一致、行数一致; 含 ( ) & 空格路径实测可读(旧黑名单实现抛"文件路径包含不允许的命令行特殊字符"); cmd 失败消息含退出码与 stderr;dotnet build -p:Platform=x86 0 错误, 警告集与 HEAD 基线完全一致。
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 = CommandTypeFileReader.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;
|
|
}
|
|
}
|
|
}
|