#0006 更新日志系统,增加 debug文件夹

This commit is contained in:
zhengxuan.zhang
2026-03-13 17:17:47 +08:00
parent 029752e231
commit 59fc0d64d7
32 changed files with 645 additions and 565 deletions
+46 -10
View File
@@ -69,41 +69,77 @@ XplorePlane/
### 日志系统 ### 日志系统
项目已集成 Serilog 日志框架,提供统一的日志服务: 项目通过引用 **XplorePlane.Common.dll** 库使用统一的日志功能,无需在本项目中重复实现。
- **日志框架**: Serilog 4.3.1 - **日志框架**: Serilog 4.3.1(来自 XplorePlane.Common.dll
- **日志输出**: 控制台、文件(按天滚动)、调试输出 - **日志输出**: 控制台、文件(按天滚动)、调试输出
- **日志路径**: `logs/xploreplane-YYYYMMDD.log` - **日志路径**: `logs/xploreplane-YYYYMMDD.log`
- **配置文件**: `App.config` - **配置文件**: `App.config`
- **服务接口**: `ILoggerService` - **服务接口**: `XplorePlane.Common.Logging.Interfaces.ILoggerService`
**使用示例**: **使用方式 1 - 使用 Serilog ILogger(推荐)**:
```csharp ```csharp
using Serilog;
public class MyViewModel
{
private readonly ILogger _logger;
public MyViewModel(ILogger logger)
{
_logger = logger.ForContext<MyViewModel>();
}
public void DoSomething()
{
_logger.Information("执行操作");
_logger.Debug("调试信息:参数={Value}", someValue);
}
}
```
**使用方式 2 - 使用 XplorePlane.Common.ILoggerService**:
```csharp
using XplorePlane.Common.Logging.Interfaces;
public class MyService public class MyService
{ {
private readonly ILoggerService _logger; private readonly ILoggerService _logger;
public MyService(ILoggerService logger) public MyService(ILoggerService logger)
{ {
// 使用泛型自动推断模块名 _logger = logger.ForModule<MyService>();
_logger = logger?.ForModule<MyService>() ?? throw new ArgumentNullException(nameof(logger));
} }
public void DoSomething() public void DoWork()
{ {
_logger.Info("执行操作"); _logger.Info("开始工作");
_logger.Debug("调试信息:参数={Value}", someValue); _logger.Debug("调试信息:参数={Value}", someValue);
} }
} }
``` ```
详细使用指南请参考:`Doc/Logging.README.md` 详细使用指南请参考:
- [快速开始指南](QUICK_START.md)
- [日志集成说明](Doc/LOGGING_INTEGRATION.md)
- [日志使用示例](Services/LoggingUsageExample.cs)
### TO-DO List ### TO-DO List
- [x] 软件基于 WPF + Prism 基础的框架 - [x] 软件基于 WPF + Prism 基础的框架
- [x] 日志库的引用 - [x] 日志库的引用(通过 XplorePlane.Common.dll
- [x] 按推荐的 DLL 目录结构进行修改
- [x] 通过库依赖的方式调用日志功能
- [ ] 界面的布局 - [ ] 界面的布局
- [ ] 打通与硬件层的调用流程 - [ ] 打通与硬件层的调用流程
- [ ] 打通与图像层的调用流程 - [ ] 打通与图像层的调用流程
### 文档
- [快速开始指南](QUICK_START.md) - 快速上手指南
- [DLL 集成方案](Doc/DLL_INTEGRATION.md) - 硬件库 DLL 集成方案
- [日志集成说明](Doc/LOGGING_INTEGRATION.md) - 日志系统集成说明
- [项目架构](Doc/PROJECT_ARCHITECTURE.md) - 项目整体架构
- [硬件集成技术方案](Doc/HARDWARE_INTEGRATION_TECHNICAL_SCHEME.md) - 硬件集成技术方案
+10 -6
View File
@@ -2,10 +2,10 @@
using System.Windows; using System.Windows;
using XplorePlane.Views; using XplorePlane.Views;
using XplorePlane.ViewModels; using XplorePlane.ViewModels;
using XplorePlane.Services;
using Prism.Ioc; using Prism.Ioc;
using Prism.DryIoc; using Prism.DryIoc;
using Serilog; using Serilog;
using XplorePlane.Common.Logging;
namespace XplorePlane namespace XplorePlane
{ {
@@ -16,8 +16,8 @@ namespace XplorePlane
{ {
protected override void OnStartup(StartupEventArgs e) protected override void OnStartup(StartupEventArgs e)
{ {
// 配置 Serilog 日志系统 // 使用 XplorePlane.Common.dll 中的日志配置
SerilogConfig.Configure(); LoggerConfig.Initialize("XplorePlane");
// 捕获未处理的异常 // 捕获未处理的异常
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
@@ -33,7 +33,8 @@ namespace XplorePlane
protected override void OnExit(ExitEventArgs e) protected override void OnExit(ExitEventArgs e)
{ {
// 关闭并刷新日志 // 关闭并刷新日志
SerilogConfig.CloseAndFlush(); Log.Information("XplorePlane 应用程序退出");
Log.CloseAndFlush();
base.OnExit(e); base.OnExit(e);
} }
@@ -79,8 +80,11 @@ namespace XplorePlane
protected override void RegisterTypes(IContainerRegistry containerRegistry) protected override void RegisterTypes(IContainerRegistry containerRegistry)
{ {
// 注册日志服务 // 注册 Serilog 的 ILogger 实例
containerRegistry.RegisterSingleton<ILoggerService, LoggerService>(); containerRegistry.RegisterInstance<ILogger>(Log.Logger);
// 注册 XplorePlane.Common.ILoggerService 适配器
containerRegistry.RegisterSingleton<XplorePlane.Common.Logging.Interfaces.ILoggerService, Services.LoggerServiceAdapter>();
// 注册视图和视图模型 // 注册视图和视图模型
containerRegistry.RegisterForNavigation<MainWindow>(); containerRegistry.RegisterForNavigation<MainWindow>();
Binary file not shown.
-90
View File
@@ -1,90 +0,0 @@
using System;
namespace XplorePlane.Services
{
/// <summary>
/// 日志服务接口
/// </summary>
public interface ILoggerService
{
/// <summary>
/// 为指定模块创建日志器(使用泛型自动推断类型名)
/// </summary>
ILoggerService ForModule<T>();
/// <summary>
/// 为指定模块创建日志器(手动指定模块名)
/// </summary>
ILoggerService ForModule(string moduleName);
/// <summary>
/// 记录调试信息
/// </summary>
void Debug(string message);
/// <summary>
/// 记录调试信息(带参数)
/// </summary>
void Debug(string messageTemplate, params object[] propertyValues);
/// <summary>
/// 记录一般信息
/// </summary>
void Info(string message);
/// <summary>
/// 记录一般信息(带参数)
/// </summary>
void Info(string messageTemplate, params object[] propertyValues);
/// <summary>
/// 记录警告信息
/// </summary>
void Warn(string message);
/// <summary>
/// 记录警告信息(带参数)
/// </summary>
void Warn(string messageTemplate, params object[] propertyValues);
/// <summary>
/// 记录错误信息
/// </summary>
void Error(string message);
/// <summary>
/// 记录错误信息(带参数)
/// </summary>
void Error(string messageTemplate, params object[] propertyValues);
/// <summary>
/// 记录错误信息(带异常)
/// </summary>
void Error(Exception exception, string message);
/// <summary>
/// 记录错误信息(带异常和参数)
/// </summary>
void Error(Exception exception, string messageTemplate, params object[] propertyValues);
/// <summary>
/// 记录致命错误
/// </summary>
void Fatal(string message);
/// <summary>
/// 记录致命错误(带参数)
/// </summary>
void Fatal(string messageTemplate, params object[] propertyValues);
/// <summary>
/// 记录致命错误(带异常)
/// </summary>
void Fatal(Exception exception, string message);
/// <summary>
/// 记录致命错误(带异常和参数)
/// </summary>
void Fatal(Exception exception, string messageTemplate, params object[] propertyValues);
}
}
@@ -1,35 +1,36 @@
using System; using System;
using Serilog; using Serilog;
using Serilog.Core; using XplorePlane.Common.Logging.Interfaces;
namespace XplorePlane.Services namespace XplorePlane.Services
{ {
/// <summary> /// <summary>
/// 日志服务实现 /// 日志服务适配器
/// 将 Serilog ILogger 适配为 XplorePlane.Common.ILoggerService 接口
/// </summary> /// </summary>
public class LoggerService : ILoggerService public class LoggerServiceAdapter : ILoggerService
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly string _moduleName; private readonly string _moduleName;
/// <summary> /// <summary>
/// 构造函数 /// 构造函数(使用全局 Logger
/// </summary> /// </summary>
public LoggerService() : this(Log.Logger, null) public LoggerServiceAdapter() : this(Log.Logger, null)
{ {
} }
/// <summary> /// <summary>
/// 构造函数(指定 Serilog Logger /// 构造函数(指定 Serilog Logger
/// </summary> /// </summary>
public LoggerService(ILogger logger) : this(logger, null) public LoggerServiceAdapter(ILogger logger) : this(logger, null)
{ {
} }
/// <summary> /// <summary>
/// 私有构造函数(用于创建带模块名的实例) /// 私有构造函数(用于创建带模块名的实例)
/// </summary> /// </summary>
private LoggerService(ILogger logger, string moduleName) private LoggerServiceAdapter(ILogger logger, string moduleName)
{ {
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_moduleName = moduleName; _moduleName = moduleName;
@@ -41,7 +42,8 @@ namespace XplorePlane.Services
public ILoggerService ForModule<T>() public ILoggerService ForModule<T>()
{ {
var typeName = typeof(T).FullName ?? typeof(T).Name; var typeName = typeof(T).FullName ?? typeof(T).Name;
return new LoggerService(_logger, typeName); var contextLogger = _logger.ForContext("SourceContext", typeName);
return new LoggerServiceAdapter(contextLogger, typeName);
} }
/// <summary> /// <summary>
@@ -52,99 +54,86 @@ namespace XplorePlane.Services
if (string.IsNullOrWhiteSpace(moduleName)) if (string.IsNullOrWhiteSpace(moduleName))
throw new ArgumentException("模块名不能为空", nameof(moduleName)); throw new ArgumentException("模块名不能为空", nameof(moduleName));
return new LoggerService(_logger, moduleName); var contextLogger = _logger.ForContext("SourceContext", moduleName);
return new LoggerServiceAdapter(contextLogger, moduleName);
} }
/// <summary> /// <summary>
/// 获取带模块名的日志器 /// 获取当前日志器
/// </summary> /// </summary>
private ILogger GetLogger() private ILogger GetLogger()
{ {
if (string.IsNullOrEmpty(_moduleName)) return _logger;
return _logger;
return _logger.ForContext("Module", _moduleName);
} }
public void Debug(string message) public void Debug(string message)
{ {
GetLogger().Debug(FormatMessage(message)); GetLogger().Debug(message);
} }
public void Debug(string messageTemplate, params object[] propertyValues) public void Debug(string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Debug(FormatMessage(messageTemplate), propertyValues); GetLogger().Debug(messageTemplate, propertyValues);
} }
public void Info(string message) public void Info(string message)
{ {
GetLogger().Information(FormatMessage(message)); GetLogger().Information(message);
} }
public void Info(string messageTemplate, params object[] propertyValues) public void Info(string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Information(FormatMessage(messageTemplate), propertyValues); GetLogger().Information(messageTemplate, propertyValues);
} }
public void Warn(string message) public void Warn(string message)
{ {
GetLogger().Warning(FormatMessage(message)); GetLogger().Warning(message);
} }
public void Warn(string messageTemplate, params object[] propertyValues) public void Warn(string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Warning(FormatMessage(messageTemplate), propertyValues); GetLogger().Warning(messageTemplate, propertyValues);
} }
public void Error(string message) public void Error(string message)
{ {
GetLogger().Error(FormatMessage(message)); GetLogger().Error(message);
} }
public void Error(string messageTemplate, params object[] propertyValues) public void Error(string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Error(FormatMessage(messageTemplate), propertyValues); GetLogger().Error(messageTemplate, propertyValues);
} }
public void Error(Exception exception, string message) public void Error(Exception exception, string message)
{ {
GetLogger().Error(exception, FormatMessage(message)); GetLogger().Error(exception, message);
} }
public void Error(Exception exception, string messageTemplate, params object[] propertyValues) public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Error(exception, FormatMessage(messageTemplate), propertyValues); GetLogger().Error(exception, messageTemplate, propertyValues);
} }
public void Fatal(string message) public void Fatal(string message)
{ {
GetLogger().Fatal(FormatMessage(message)); GetLogger().Fatal(message);
} }
public void Fatal(string messageTemplate, params object[] propertyValues) public void Fatal(string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Fatal(FormatMessage(messageTemplate), propertyValues); GetLogger().Fatal(messageTemplate, propertyValues);
} }
public void Fatal(Exception exception, string message) public void Fatal(Exception exception, string message)
{ {
GetLogger().Fatal(exception, FormatMessage(message)); GetLogger().Fatal(exception, message);
} }
public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues) public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues)
{ {
GetLogger().Fatal(exception, FormatMessage(messageTemplate), propertyValues); GetLogger().Fatal(exception, messageTemplate, propertyValues);
}
/// <summary>
/// 格式化消息(添加模块名前缀)
/// </summary>
private string FormatMessage(string message)
{
if (string.IsNullOrEmpty(_moduleName))
return message;
return $"[{_moduleName}] {message}";
} }
} }
} }
-139
View File
@@ -1,139 +0,0 @@
using System;
using System.Threading.Tasks;
namespace XplorePlane.Services
{
/// <summary>
/// 日志服务使用示例
/// </summary>
public class LoggingExample
{
private readonly ILoggerService _logger;
public LoggingExample(ILoggerService logger)
{
// 推荐方式:使用泛型自动推断类型名
_logger = logger?.ForModule<LoggingExample>() ?? throw new ArgumentNullException(nameof(logger));
}
/// <summary>
/// 基本日志示例
/// </summary>
public void BasicLoggingExample()
{
// 调试信息
_logger.Debug("这是调试信息");
// 一般信息
_logger.Info("应用程序启动成功");
// 警告信息
_logger.Warn("连接不稳定,正在重试...");
// 错误信息
_logger.Error("操作失败");
// 致命错误
_logger.Fatal("系统崩溃");
}
/// <summary>
/// 结构化日志示例
/// </summary>
public void StructuredLoggingExample()
{
var userId = 12345;
var action = "登录";
var voltage = 150.5f;
var current = 500;
// 使用占位符(推荐)
_logger.Info("用户 {UserId} 执行了操作 {Action}", userId, action);
_logger.Info("设置电压为 {Voltage} kV,电流为 {Current} μA", voltage, current);
// 不推荐:字符串拼接
// _logger.Info($"用户 {userId} 执行了操作 {action}");
}
/// <summary>
/// 异常日志示例
/// </summary>
public async Task ExceptionLoggingExample()
{
try
{
// 模拟操作
await Task.Delay(100);
throw new InvalidOperationException("模拟异常");
}
catch (Exception ex)
{
// 记录异常(带上下文信息)
_logger.Error(ex, "操作失败:参数={Parameter}", "test");
// 或者简单记录
_logger.Error(ex, "操作失败");
// 致命错误
_logger.Fatal(ex, "系统发生致命错误");
}
}
/// <summary>
/// 不同模块名示例
/// </summary>
public void DifferentModuleNameExample(ILoggerService logger)
{
// 方式 1:使用泛型(推荐)
var logger1 = logger.ForModule<LoggingExample>();
logger1.Info("使用泛型推断的模块名");
// 输出: [XplorePlane.Services.LoggingExample] 使用泛型推断的模块名
// 方式 2:手动指定模块名
var logger2 = logger.ForModule("CustomModule");
logger2.Info("使用自定义模块名");
// 输出: [CustomModule] 使用自定义模块名
// 方式 3:不指定模块名
logger.Info("没有模块名");
// 输出: 没有模块名
}
/// <summary>
/// 实际业务场景示例
/// </summary>
public async Task<bool> BusinessScenarioExample()
{
_logger.Info("开始初始化硬件...");
try
{
// 步骤 1
_logger.Debug("步骤 1: 检查硬件连接");
await Task.Delay(100);
// 步骤 2
_logger.Debug("步骤 2: 加载配置");
var config = LoadConfig();
_logger.Info("配置加载成功:{ConfigName}", config);
// 步骤 3
_logger.Debug("步骤 3: 建立连接");
await Task.Delay(100);
_logger.Info("硬件初始化成功");
return true;
}
catch (Exception ex)
{
_logger.Error(ex, "硬件初始化失败");
return false;
}
}
private string LoadConfig()
{
return "DefaultConfig";
}
}
}
@@ -1,94 +0,0 @@
using System;
using System.Threading.Tasks;
namespace XplorePlane.Services
{
/// <summary>
/// 日志系统验证类 - 用于测试日志功能是否正常工作
/// </summary>
public class LoggingVerification
{
private readonly ILoggerService _logger;
public LoggingVerification(ILoggerService logger)
{
_logger = logger?.ForModule<LoggingVerification>() ?? throw new ArgumentNullException(nameof(logger));
}
/// <summary>
/// 运行完整的日志验证测试
/// </summary>
public async Task RunVerificationAsync()
{
_logger.Info("========================================");
_logger.Info("开始日志系统验证测试");
_logger.Info("========================================");
// 测试 1: 基本日志级别
TestBasicLogLevels();
// 测试 2: 结构化日志
TestStructuredLogging();
// 测试 3: 异常日志
await TestExceptionLoggingAsync();
// 测试 4: 模块名
TestModuleNames();
_logger.Info("========================================");
_logger.Info("日志系统验证测试完成");
_logger.Info("========================================");
}
private void TestBasicLogLevels()
{
_logger.Info("测试 1: 基本日志级别");
_logger.Debug("这是 Debug 级别日志");
_logger.Info("这是 Info 级别日志");
_logger.Warn("这是 Warn 级别日志");
_logger.Error("这是 Error 级别日志");
_logger.Info("✓ 基本日志级别测试完成");
}
private void TestStructuredLogging()
{
_logger.Info("测试 2: 结构化日志");
var userId = 12345;
var userName = "张三";
var voltage = 150.5f;
var current = 500;
var timestamp = DateTime.Now;
_logger.Info("用户登录: UserId={UserId}, UserName={UserName}", userId, userName);
_logger.Info("设置参数: Voltage={Voltage}kV, Current={Current}μA", voltage, current);
_logger.Info("操作时间: {Timestamp:yyyy-MM-dd HH:mm:ss}", timestamp);
_logger.Info("✓ 结构化日志测试完成");
}
private async Task TestExceptionLoggingAsync()
{
_logger.Info("测试 3: 异常日志");
try
{
await Task.Delay(10);
throw new InvalidOperationException("这是一个测试异常");
}
catch (Exception ex)
{
_logger.Error(ex, "捕获到异常: {Message}", ex.Message);
_logger.Info("✓ 异常日志测试完成");
}
}
private void TestModuleNames()
{
_logger.Info("测试 4: 模块名功能");
_logger.Info("当前模块名应该是: XplorePlane.Services.LoggingVerification");
_logger.Info("✓ 模块名测试完成");
}
}
}
+100 -51
View File
@@ -1,75 +1,124 @@
# Services 目录说明 # XplorePlane 服务层
此目录用于存放应用程序的服务层代码,负责封装硬件库的调用和业务逻辑。 ## 概述
## 目录结构 本目录包含 XplorePlane 应用程序的服务层实现。服务层负责封装业务逻辑和硬件交互。
``` ## 日志服务
Services/
├── IHardwareService.cs # 硬件服务接口
├── HardwareService.cs # 硬件服务实现
├── IConfigurationService.cs # 配置服务接口
└── ConfigurationService.cs # 配置服务实现
```
## 服务说明 XplorePlane 使用 **XplorePlane.Common.dll** 库中封装的日志功能,无需在本项目中重复实现。
### 1. HardwareService ### 使用方式
统一管理所有硬件模块的服务适配器。 #### 1. 通过依赖注入使用 Serilog ILogger
**功能**
- 初始化和关闭所有硬件
- 射线源控制(开关、参数设置)
- 探测器控制(图像采集、配置)
- PLC 通讯(变量读写)
**使用示例**
```csharp ```csharp
// 在 ViewModel 中注入 using Serilog;
public class MainViewModel
{
private readonly IHardwareService _hardwareService;
public MainViewModel(IHardwareService hardwareService) public class MyViewModel
{
private readonly ILogger _logger;
public MyViewModel(ILogger logger)
{ {
_hardwareService = hardwareService; _logger = logger;
} }
public async Task InitializeAsync() public void DoSomething()
{ {
await _hardwareService.InitializeAllAsync(); _logger.Information("执行某个操作");
_logger.Warning("警告信息");
_logger.Error("错误信息");
} }
} }
``` ```
### 2. ConfigurationService #### 2. 使用静态 Log 类
管理应用程序配置的服务。
**功能**
- 读取 App.config 配置
- 类型安全的配置访问
- 默认值支持
## 依赖注入配置
`App.xaml.cs` 中注册服务:
```csharp ```csharp
protected override void RegisterTypes(IContainerRegistry containerRegistry) using Serilog;
{
// 注册硬件服务
containerRegistry.RegisterSingleton<IHardwareService, HardwareService>();
// 注册配置服务 public class MyService
containerRegistry.RegisterSingleton<IConfigurationService, ConfigurationService>(); {
public void DoWork()
{
Log.Information("开始工作");
Log.Debug("调试信息: {Value}", someValue);
Log.Error(exception, "发生错误");
}
} }
``` ```
## 注意事项 #### 3. 为特定模块创建日志器
1. **服务生命周期**:硬件服务应注册为 Singleton,确保全局唯一 ```csharp
2. **异步操作**:所有硬件操作都应使用异步方法 using Serilog;
3. **错误处理**:服务层应捕获并记录所有异常
4. **资源释放**:实现 IDisposable 接口,确保资源正确释放 public class RaySourceService
{
private readonly ILogger _logger;
public RaySourceService()
{
// 为当前类创建带上下文的日志器
_logger = Log.ForContext<RaySourceService>();
}
public void Initialize()
{
_logger.Information("初始化射线源");
}
}
```
### 日志配置
日志配置通过 `App.config` 文件进行管理:
```xml
<appSettings>
<!-- 日志配置 -->
<add key="Serilog:LogPath" value="logs"/>
<add key="Serilog:MinimumLevel" value="Information"/>
<add key="Serilog:EnableConsole" value="true"/>
<add key="Serilog:RollingInterval" value="Day"/>
<add key="Serilog:FileSizeLimitMB" value="100"/>
<add key="Serilog:RetainedFileCountLimit" value="30"/>
</appSettings>
```
### 日志级别
- **Verbose**: 最详细的日志,用于开发调试
- **Debug**: 调试信息
- **Information**: 一般信息(默认)
- **Warning**: 警告信息
- **Error**: 错误信息
- **Fatal**: 致命错误
### 日志输出
日志会输出到以下位置:
- 文件: `logs/xploreplane-{Date}.log`
- 控制台: 开发时可见
- 调试输出: Debug 模式下可见
## 硬件服务
硬件服务将在后续实现,用于封装与硬件库的交互。
### 计划实现的服务
- `IHardwareService`: 硬件服务总接口
- `RaySourceService`: 射线源控制服务
- `DetectorService`: 探测器控制服务
- `PLCService`: PLC 通讯服务
## 依赖库
- **XplorePlane.Common.dll**: 通用基础设施库(包含日志功能)
- **XplorePlane.Hardware.RaySource.dll**: 射线源控制库
- **XplorePlane.Hardware.Detector.dll**: 探测器控制库
- **XplorePlane.Hardware.PLC.dll**: PLC 通讯库
所有 DLL 文件位于 `Libs/Hardware/` 目录下。
-133
View File
@@ -1,133 +0,0 @@
using System;
using System.Configuration;
using System.IO;
using Serilog;
using Serilog.Events;
namespace XplorePlane.Services
{
/// <summary>
/// Serilog 配置类
/// </summary>
public static class SerilogConfig
{
/// <summary>
/// 配置 Serilog
/// </summary>
public static void Configure()
{
// 读取配置
var logPath = GetConfigValue("Serilog:LogPath", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"));
var minimumLevel = GetLogLevel(GetConfigValue("Serilog:MinimumLevel", "Information"));
var enableConsole = GetConfigValue("Serilog:EnableConsole", "true").ToLower() == "true";
var rollingInterval = GetRollingInterval(GetConfigValue("Serilog:RollingInterval", "Day"));
var fileSizeLimitMB = int.Parse(GetConfigValue("Serilog:FileSizeLimitMB", "100"));
var retainedFileCountLimit = int.Parse(GetConfigValue("Serilog:RetainedFileCountLimit", "30"));
// 确保日志目录存在
if (!Directory.Exists(logPath))
{
Directory.CreateDirectory(logPath);
}
// 配置 Serilog
var loggerConfig = new LoggerConfiguration()
.MinimumLevel.Is(minimumLevel)
.Enrich.FromLogContext()
.Enrich.WithProperty("Application", "XplorePlane")
.Enrich.WithProperty("MachineName", Environment.MachineName)
.WriteTo.File(
path: Path.Combine(logPath, "xploreplane-.log"),
rollingInterval: rollingInterval,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
fileSizeLimitBytes: fileSizeLimitMB * 1024 * 1024,
retainedFileCountLimit: retainedFileCountLimit,
shared: true
);
// 添加控制台输出
if (enableConsole)
{
loggerConfig.WriteTo.Console(
outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
);
}
// 添加调试输出(仅在 Debug 模式)
#if DEBUG
loggerConfig.WriteTo.Debug(
outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
);
#endif
// 创建全局 Logger
Log.Logger = loggerConfig.CreateLogger();
Log.Information("========================================");
Log.Information("XplorePlane 应用程序启动");
Log.Information("日志路径: {LogPath}", logPath);
Log.Information("日志级别: {MinimumLevel}", minimumLevel);
Log.Information("========================================");
}
/// <summary>
/// 关闭并刷新日志
/// </summary>
public static void CloseAndFlush()
{
Log.Information("========================================");
Log.Information("XplorePlane 应用程序退出");
Log.Information("========================================");
Log.CloseAndFlush();
}
/// <summary>
/// 获取配置值
/// </summary>
private static string GetConfigValue(string key, string defaultValue)
{
try
{
return ConfigurationManager.AppSettings[key] ?? defaultValue;
}
catch
{
return defaultValue;
}
}
/// <summary>
/// 获取日志级别
/// </summary>
private static LogEventLevel GetLogLevel(string level)
{
return level.ToLower() switch
{
"verbose" => LogEventLevel.Verbose,
"debug" => LogEventLevel.Debug,
"information" => LogEventLevel.Information,
"warning" => LogEventLevel.Warning,
"error" => LogEventLevel.Error,
"fatal" => LogEventLevel.Fatal,
_ => LogEventLevel.Information
};
}
/// <summary>
/// 获取滚动间隔
/// </summary>
private static RollingInterval GetRollingInterval(string interval)
{
return interval.ToLower() switch
{
"infinite" => RollingInterval.Infinite,
"year" => RollingInterval.Year,
"month" => RollingInterval.Month,
"day" => RollingInterval.Day,
"hour" => RollingInterval.Hour,
"minute" => RollingInterval.Minute,
_ => RollingInterval.Day
};
}
}
}
+52 -4
View File
@@ -6,31 +6,79 @@
<RootNamespace>XplorePlane</RootNamespace> <RootNamespace>XplorePlane</RootNamespace>
<AssemblyName>XplorePlane</AssemblyName> <AssemblyName>XplorePlane</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="MainWindow.xaml.cs" /> <Compile Remove="MainWindow.xaml.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="XplorePlane.csproj.Backup.tmp" /> <None Remove="XplorePlane.csproj.Backup.tmp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Remove="MainWindow.xaml" /> <Page Remove="MainWindow.xaml" />
</ItemGroup> </ItemGroup>
<!-- NuGet 包引用 -->
<ItemGroup> <ItemGroup>
<PackageReference Include="Prism.DryIoc" Version="9.0.537" /> <PackageReference Include="Prism.DryIoc" Version="9.0.537" />
<PackageReference Include="Fluent.Ribbon" Version="9.0.0" /> <PackageReference Include="Fluent.Ribbon" Version="9.0.0" />
<!-- Serilog 日志框架 --> <!-- 硬件库依赖的 NuGet 包 -->
<PackageReference Include="Serilog" Version="4.3.1" /> <PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" /> <PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
<!-- 配置管理 -->
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" /> <PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<!-- 确保 App.config 复制到输出目录 --> <!-- DLL 引用 -->
<ItemGroup> <ItemGroup>
<!-- 硬件库 DLL 引用 -->
<Reference Include="XplorePlane.Common">
<HintPath>Libs\Hardware\XplorePlane.Common.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="XplorePlane.Hardware.RaySource">
<HintPath>Libs\Hardware\XplorePlane.Hardware.RaySource.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="XplorePlane.Hardware.Detector">
<HintPath>Libs\Hardware\XplorePlane.Hardware.Detector.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="XplorePlane.Hardware.PLC">
<HintPath>Libs\Hardware\XplorePlane.Hardware.PLC.dll</HintPath>
<Private>True</Private>
</Reference>
<!-- 原生依赖库引用 -->
<Reference Include="BR.AN.PviServices">
<HintPath>Libs\Native\BR.AN.PviServices.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<!-- 确保 DLL 和原生库复制到输出目录 -->
<ItemGroup>
<!-- 硬件库 DLL -->
<None Include="Libs\Hardware\*.dll" Condition="Exists('Libs\Hardware')">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Libs\Hardware\*.pdb" Condition="Exists('Libs\Hardware')">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<!-- 原生依赖库 -->
<None Include="Libs\Native\*.dll" Condition="Exists('Libs\Native')">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<!-- 配置文件 -->
<None Update="App.config"> <None Update="App.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Serilog 日志配置 -->
<add key="Serilog:LogPath" value="logs" />
<add key="Serilog:MinimumLevel" value="Information" />
<add key="Serilog:EnableConsole" value="true" />
<add key="Serilog:RollingInterval" value="Day" />
<add key="Serilog:FileSizeLimitMB" value="100" />
<add key="Serilog:RetainedFileCountLimit" value="30" />
<!-- 射线源配置 -->
<add key="RaySource.Type" value="Comet225"/>
<add key="RaySource.StationName" value="XRAY_STATION"/>
<add key="RaySource.ConnectionTimeout" value="5000"/>
<add key="RaySource.VoltageMin" value="20"/>
<add key="RaySource.VoltageMax" value="225"/>
<add key="RaySource.CurrentMin" value="10"/>
<add key="RaySource.CurrentMax" value="1000"/>
<!-- 探测器配置 -->
<add key="Detector.Type" value="Varex4343"/>
<add key="Detector.IPAddress" value="192.168.1.101"/>
<add key="Detector.Port" value="8080"/>
<!-- PLC 配置 -->
<add key="PLC.Type" value="B&amp;R"/>
<add key="PLC.StationName" value="PLC_STATION"/>
<add key="PLC.ConnectionTimeout" value="5000"/>
</appSettings>
</configuration>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,329 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {
"XplorePlane/1.0.0": {
"dependencies": {
"Fluent.Ribbon": "9.0.0",
"Prism.DryIoc": "9.0.537",
"Serilog": "4.3.1",
"Serilog.Sinks.Console": "6.1.1",
"Serilog.Sinks.Debug": "3.0.0",
"Serilog.Sinks.File": "7.0.0",
"System.Configuration.ConfigurationManager": "8.0.0"
},
"runtime": {
"XplorePlane.dll": {}
}
},
"ControlzEx/5.0.1": {
"dependencies": {
"Microsoft.Xaml.Behaviors.Wpf": "1.1.122",
"System.Text.Json": "5.0.1"
},
"runtime": {
"lib/net5.0-windows7.0/ControlzEx.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.1.15"
}
}
},
"DryIoc.dll/5.4.3": {
"runtime": {
"lib/net7.0/DryIoc.dll": {
"assemblyVersion": "5.4.3.0",
"fileVersion": "5.4.3.0"
}
}
},
"Fluent.Ribbon/9.0.0": {
"dependencies": {
"ControlzEx": "5.0.1"
},
"runtime": {
"lib/net5.0-windows7.0/Fluent.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/8.0.1": {
"runtime": {
"lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.324.11423"
}
}
},
"Microsoft.Xaml.Behaviors.Wpf/1.1.122": {
"runtime": {
"lib/net6.0-windows7.0/Microsoft.Xaml.Behaviors.dll": {
"assemblyVersion": "1.1.0.0",
"fileVersion": "1.1.122.28819"
}
}
},
"Prism.Container.Abstractions/9.0.106": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1"
},
"runtime": {
"lib/net8.0/Prism.Container.Abstractions.dll": {
"assemblyVersion": "9.0.106.9543",
"fileVersion": "9.0.106.9543"
}
}
},
"Prism.Container.DryIoc/9.0.106": {
"dependencies": {
"DryIoc.dll": "5.4.3",
"Prism.Container.Abstractions": "9.0.106"
},
"runtime": {
"lib/net8.0/Prism.Container.DryIoc.dll": {
"assemblyVersion": "9.0.106.9543",
"fileVersion": "9.0.106.9543"
}
}
},
"Prism.Core/9.0.537": {
"dependencies": {
"Prism.Container.Abstractions": "9.0.106",
"Prism.Events": "9.0.537"
},
"runtime": {
"lib/net6.0/Prism.dll": {
"assemblyVersion": "9.0.537.60525",
"fileVersion": "9.0.537.60525"
}
}
},
"Prism.DryIoc/9.0.537": {
"dependencies": {
"Prism.Container.DryIoc": "9.0.106",
"Prism.Wpf": "9.0.537"
},
"runtime": {
"lib/net6.0-windows7.0/Prism.DryIoc.Wpf.dll": {
"assemblyVersion": "9.0.537.60525",
"fileVersion": "9.0.537.60525"
}
}
},
"Prism.Events/9.0.537": {
"runtime": {
"lib/net6.0/Prism.Events.dll": {
"assemblyVersion": "9.0.537.60525",
"fileVersion": "9.0.537.60525"
}
}
},
"Prism.Wpf/9.0.537": {
"dependencies": {
"Microsoft.Xaml.Behaviors.Wpf": "1.1.122",
"Prism.Core": "9.0.537"
},
"runtime": {
"lib/net6.0-windows7.0/Prism.Wpf.dll": {
"assemblyVersion": "9.0.537.60525",
"fileVersion": "9.0.537.60525"
}
}
},
"Serilog/4.3.1": {
"runtime": {
"lib/net8.0/Serilog.dll": {
"assemblyVersion": "4.3.0.0",
"fileVersion": "4.3.0.0"
}
}
},
"Serilog.Sinks.Console/6.1.1": {
"dependencies": {
"Serilog": "4.3.1"
},
"runtime": {
"lib/net8.0/Serilog.Sinks.Console.dll": {
"assemblyVersion": "6.1.1.0",
"fileVersion": "6.1.1.0"
}
}
},
"Serilog.Sinks.Debug/3.0.0": {
"dependencies": {
"Serilog": "4.3.1"
},
"runtime": {
"lib/net8.0/Serilog.Sinks.Debug.dll": {
"assemblyVersion": "3.0.0.0",
"fileVersion": "3.0.0.0"
}
}
},
"Serilog.Sinks.File/7.0.0": {
"dependencies": {
"Serilog": "4.3.1"
},
"runtime": {
"lib/net8.0/Serilog.Sinks.File.dll": {
"assemblyVersion": "7.0.0.0",
"fileVersion": "7.0.0.0"
}
}
},
"System.Configuration.ConfigurationManager/8.0.0": {
"dependencies": {
"System.Diagnostics.EventLog": "8.0.0",
"System.Security.Cryptography.ProtectedData": "8.0.0"
}
},
"System.Diagnostics.EventLog/8.0.0": {},
"System.Security.Cryptography.ProtectedData/8.0.0": {},
"System.Text.Json/5.0.1": {}
}
},
"libraries": {
"XplorePlane/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"ControlzEx/5.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DVJJmmnKXcVh3Bs2gKpAdPCT8HrkYTagSbFg0P9xHjp8dox9bKeaoVj9VGhPRzP9+LHs5MUXxN07/oGqeXNNcg==",
"path": "controlzex/5.0.1",
"hashPath": "controlzex.5.0.1.nupkg.sha512"
},
"DryIoc.dll/5.4.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-yhXOG3SOxeWYxBAWskNRDD8fzw5hriEawv4VN4WKaFHOuubiop4kxe2rkWTEyCnTgRVgxVUSQCDBBkZqwPm1iQ==",
"path": "dryioc.dll/5.4.3",
"hashPath": "dryioc.dll.5.4.3.nupkg.sha512"
},
"Fluent.Ribbon/9.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-29N3G7EM1WFgNofj4wEaufFaB8Iakjn/CZskq3kHKR93myxJ2iV0k6xLH3rhg9l/QATboPExV0WONT/ZfQcOVg==",
"path": "fluent.ribbon/9.0.0",
"hashPath": "fluent.ribbon.9.0.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/8.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fGLiCRLMYd00JYpClraLjJTNKLmMJPnqxMaiRzEBIIvevlzxz33mXy39Lkd48hu1G+N21S7QpaO5ZzKsI6FRuA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/8.0.1",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.8.0.1.nupkg.sha512"
},
"Microsoft.Xaml.Behaviors.Wpf/1.1.122": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SgcafT189u4qX++vSCV9FLQ4BsRXU9J2esnHA9IF8GOSgnPBulFw1CW4X/FYoOXvZwdDZxlSObJUGUg1U1wSyg==",
"path": "microsoft.xaml.behaviors.wpf/1.1.122",
"hashPath": "microsoft.xaml.behaviors.wpf.1.1.122.nupkg.sha512"
},
"Prism.Container.Abstractions/9.0.106": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QNOERNOqsxvAa8pbWjqFB872DkvYK/cVRrcFO5vJYgWTIKBd8xfaI/jaZ0qeXLYVDz0nrvgJTZVVnip6+68dCw==",
"path": "prism.container.abstractions/9.0.106",
"hashPath": "prism.container.abstractions.9.0.106.nupkg.sha512"
},
"Prism.Container.DryIoc/9.0.106": {
"type": "package",
"serviceable": true,
"sha512": "sha512-g7UzyK4oRPmEGgz2CV976KTBFk+QPdfktyrL91kvI4YbHciQATO6/r1KFnyRnBE73il5v+SeXXKWIrvlMnsMdg==",
"path": "prism.container.dryioc/9.0.106",
"hashPath": "prism.container.dryioc.9.0.106.nupkg.sha512"
},
"Prism.Core/9.0.537": {
"type": "package",
"serviceable": true,
"sha512": "sha512-D7mEqPKLVNrD0g2WHCpC/MOKwn8h7X1liCWyjqjL7NCuxgwuhVLTG85E/ZPBkISrXdwvOQZ+bSY31bvP79FQlg==",
"path": "prism.core/9.0.537",
"hashPath": "prism.core.9.0.537.nupkg.sha512"
},
"Prism.DryIoc/9.0.537": {
"type": "package",
"serviceable": true,
"sha512": "sha512-tnKifVxlKeSbNP2gZi+nMcjsi/w0lm3aLhBh92gWO6uCoa44ACM9gVJeO77ew4aHYZuoHUd6wHyeozfN7QKWuA==",
"path": "prism.dryioc/9.0.537",
"hashPath": "prism.dryioc.9.0.537.nupkg.sha512"
},
"Prism.Events/9.0.537": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==",
"path": "prism.events/9.0.537",
"hashPath": "prism.events.9.0.537.nupkg.sha512"
},
"Prism.Wpf/9.0.537": {
"type": "package",
"serviceable": true,
"sha512": "sha512-srsXhi7FRUFawsNoRkY67duMEGjZo3ff0FpqpkjeWkkAuLazlH1UmNVrvwnpaLQCBboexH/z6oGrLvpeocxgdw==",
"path": "prism.wpf/9.0.537",
"hashPath": "prism.wpf.9.0.537.nupkg.sha512"
},
"Serilog/4.3.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-savYe7h5yRlkqBVOwP8cIRDOdqKiPmYCU4W87JH38sBmcKD5EBoXvQIw6bNEvZ/pTe1gsiye3VFCzBsoppGkXQ==",
"path": "serilog/4.3.1",
"hashPath": "serilog.4.3.1.nupkg.sha512"
},
"Serilog.Sinks.Console/6.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-8jbqgjUyZlfCuSTaJk6lOca465OndqOz3KZP6Cryt/IqZYybyBu7GP0fE/AXBzrrQB3EBmQntBFAvMVz1COvAA==",
"path": "serilog.sinks.console/6.1.1",
"hashPath": "serilog.sinks.console.6.1.1.nupkg.sha512"
},
"Serilog.Sinks.Debug/3.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==",
"path": "serilog.sinks.debug/3.0.0",
"hashPath": "serilog.sinks.debug.3.0.0.nupkg.sha512"
},
"Serilog.Sinks.File/7.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fKL7mXv7qaiNBUC71ssvn/dU0k9t0o45+qm2XgKAlSt19xF+ijjxyA3R6HmCgfKEKwfcfkwWjayuQtRueZFkYw==",
"path": "serilog.sinks.file/7.0.0",
"hashPath": "serilog.sinks.file.7.0.0.nupkg.sha512"
},
"System.Configuration.ConfigurationManager/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==",
"path": "system.configuration.configurationmanager/8.0.0",
"hashPath": "system.configuration.configurationmanager.8.0.0.nupkg.sha512"
},
"System.Diagnostics.EventLog/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==",
"path": "system.diagnostics.eventlog/8.0.0",
"hashPath": "system.diagnostics.eventlog.8.0.0.nupkg.sha512"
},
"System.Security.Cryptography.ProtectedData/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==",
"path": "system.security.cryptography.protecteddata/8.0.0",
"hashPath": "system.security.cryptography.protecteddata.8.0.0.nupkg.sha512"
},
"System.Text.Json/5.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-/UM3UK1dXKl8Ybysg/21gM4S8DJgkR+yLU8JwqCVbuNqQNImelntgYFAN5QxR8sJJ1kMx//hOUdf0lltosi8cQ==",
"path": "system.text.json/5.0.1",
"hashPath": "system.text.json.5.0.1.nupkg.sha512"
}
}
}
Binary file not shown.
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Serilog 日志配置 -->
<add key="Serilog:LogPath" value="logs" />
<add key="Serilog:MinimumLevel" value="Information" />
<add key="Serilog:EnableConsole" value="true" />
<add key="Serilog:RollingInterval" value="Day" />
<add key="Serilog:FileSizeLimitMB" value="100" />
<add key="Serilog:RetainedFileCountLimit" value="30" />
<!-- 射线源配置 -->
<add key="RaySource.Type" value="Comet225"/>
<add key="RaySource.StationName" value="XRAY_STATION"/>
<add key="RaySource.ConnectionTimeout" value="5000"/>
<add key="RaySource.VoltageMin" value="20"/>
<add key="RaySource.VoltageMax" value="225"/>
<add key="RaySource.CurrentMin" value="10"/>
<add key="RaySource.CurrentMax" value="1000"/>
<!-- 探测器配置 -->
<add key="Detector.Type" value="Varex4343"/>
<add key="Detector.IPAddress" value="192.168.1.101"/>
<add key="Detector.Port" value="8080"/>
<!-- PLC 配置 -->
<add key="PLC.Type" value="B&amp;R"/>
<add key="PLC.StationName" value="PLC_STATION"/>
<add key="PLC.ConnectionTimeout" value="5000"/>
</appSettings>
</configuration>
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,19 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
{
"name": "Microsoft.WindowsDesktop.App",
"version": "8.0.0"
}
],
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": true,
"CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false
}
}
}