Files
XplorePlane/XplorePlane/Services/Storage/XpDataPathService.cs
T
zhengxuan.zhang b673eeb40a 统一各项目运行时目录结构
D:\XPData
├── DataBase\          # SQLite 数据库,例如 XP.db
├── DetectorImages\    # 探测器采集图像
├── Logs\              # Serilog 运行日志
├── Dump\              # 异常 Dump 文件
├── Report\            # 报告输出目录
├── Plan\              # 工艺 / CNC / 检测程序数据
├── Tools\             # 工具相关数据
└── Data\              # 其他运行数据
2026-06-05 14:03:30 +08:00

150 lines
5.0 KiB
C#

using System;
using System.Configuration;
using System.IO;
using XP.Common.Logging.Interfaces;
namespace XplorePlane.Services.Storage
{
public class XpDataPathService : IXpDataPathService
{
internal const string RootPathSettingKey = "XpData:RootPath";
private const string DefaultRoot = @"D:\XPData";
private readonly ILoggerService _logger;
private readonly object _syncRoot = new();
private string _rootPath;
public XpDataPathService(ILoggerService logger)
{
_logger = (logger ?? throw new ArgumentNullException(nameof(logger))).ForModule<XpDataPathService>();
_rootPath = LoadConfiguredRootPath();
EnsureManagedDirectories(_rootPath);
}
public string DefaultRootPath => DefaultRoot;
public string RootPath
{
get
{
lock (_syncRoot)
{
return _rootPath;
}
}
}
public string PlanPath => EnsureSubdirectory("Plan");
public string ToolsPath => EnsureSubdirectory("Tools");
public string DataPath => EnsureSubdirectory("Data");
public string ReportPath => EnsureSubdirectory("Report");
public string LegacyInspectionDataPath => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"XplorePlane",
"InspectionResults");
public void SaveRootPath(string rootPath)
{
var normalizedRootPath = NormalizeRootPath(rootPath);
EnsureManagedDirectories(normalizedRootPath);
try
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var appSettings = config.AppSettings.Settings;
if (appSettings[RootPathSettingKey] == null)
{
appSettings.Add(RootPathSettingKey, normalizedRootPath);
}
else
{
appSettings[RootPathSettingKey].Value = normalizedRootPath;
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
catch (ConfigurationErrorsException ex)
{
_logger.Error(ex, "保存 XP 数据根目录失败:配置文件写入异常");
throw new InvalidOperationException($"保存数据根目录失败:{ex.Message}", ex);
}
catch (UnauthorizedAccessException ex)
{
_logger.Error(ex, "保存 XP 数据根目录失败:无权写入配置文件");
throw new InvalidOperationException("保存数据根目录失败:没有配置文件写入权限。", ex);
}
lock (_syncRoot)
{
_rootPath = normalizedRootPath;
}
}
private string EnsureSubdirectory(string directoryName)
{
string rootPath;
lock (_syncRoot)
{
rootPath = _rootPath;
}
EnsureManagedDirectories(rootPath);
return Path.Combine(rootPath, directoryName);
}
private string LoadConfiguredRootPath()
{
try
{
return NormalizeRootPath(ConfigurationManager.AppSettings[RootPathSettingKey]);
}
catch (Exception ex)
{
_logger.Warn("读取 XP 数据根目录失败,回退默认目录:{Message}", ex.Message);
return NormalizeRootPath(null);
}
}
private static string NormalizeRootPath(string rootPath)
{
var candidate = string.IsNullOrWhiteSpace(rootPath) ? DefaultRoot : rootPath.Trim();
try
{
var normalized = Path.GetFullPath(candidate)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
if (!Path.IsPathRooted(normalized))
{
return DefaultRoot;
}
return normalized;
}
catch
{
return DefaultRoot;
}
}
private static void EnsureManagedDirectories(string rootPath)
{
Directory.CreateDirectory(rootPath);
Directory.CreateDirectory(Path.Combine(rootPath, "Plan"));
Directory.CreateDirectory(Path.Combine(rootPath, "Tools"));
Directory.CreateDirectory(Path.Combine(rootPath, "Data"));
Directory.CreateDirectory(Path.Combine(rootPath, "DataBase"));
Directory.CreateDirectory(Path.Combine(rootPath, "DetectorImages"));
Directory.CreateDirectory(Path.Combine(rootPath, "Logs"));
Directory.CreateDirectory(Path.Combine(rootPath, "Dump"));
Directory.CreateDirectory(Path.Combine(rootPath, "Report"));
}
}
}