You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
10 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Autofac.Extensions.DependencyInjection;
using Lierda.WPFHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using SlnMesnac.Config;
using SlnMesnac.Plc;
using SlnMesnac.Rfid;
using System;
using System.Collections.Generic;
using System.Windows;
namespace SlnMesnac.WPF
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private System.Threading.Mutex? mutex = null;
private LierdaCracker cracker = new LierdaCracker();
public static IServiceProvider? ServiceProvider = null;
private static IHost? host;
private AppConfig appConfig;
// Startup事件
protected override async void OnStartup(StartupEventArgs e)
{
try
{
bool ret;
//mutex = new System.Threading.Mutex(true, System.Diagnostics.Process.GetCurrentProcess().ProcessName, out ret);
//if (!ret)
//{
// MessageBox.Show("应用程序已开启,禁止重复运行");
// Environment.Exit(0);
//}
cracker.Cracker(100); //设置GC回收间隔
base.OnStartup(e);
//var host = CreateHostBuilder(e.Args).Build();//生成宿主。
//ServiceProvider = host.Services;
//await host.StartAsync();
var instanceId = GetInstanceId(e.Args);
// 创建完全独立的Host构建器
host = CreateHostBuilder(e.Args, instanceId).Build();
// 预先验证服务
using (var scope = host.Services.CreateScope())
{
ServiceProvider = scope.ServiceProvider;
try
{
//serilogHelper = services.GetRequiredService<SerilogHelper>();
//serilogHelper.Info($"启动服务");
//var appConfig = services.GetRequiredService<AppConfig>();
appConfig = host.Services.GetService<AppConfig>();
// 强制设置实例ID到配置对象
SetInstanceSpecificConfiguration(appConfig, instanceId);
//serilogHelper.Info($"实例 {instanceId} 服务初始化完成");
Console.WriteLine($"实例 {instanceId} 服务初始化完成");
}
catch (Exception ex)
{
Console.WriteLine($"实例 {instanceId} 服务初始化失败: {ex.Message}");
//serilogHelper.Info($"详细错误: {ex}");
}
}
//await host.StartAsync();
var hostTask = host.RunAsync();
var logPath = $"{appConfig.logPath}/Logs/{DateTime.UtcNow:yyyy-MM-dd}/";
Log.Information($"系统初始化完成,日志存放路径:{appConfig.logPath}");
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
}
private static void SetInstanceSpecificConfiguration(AppConfig appConfig, string instanceId)
{
try
{
Console.WriteLine($"为实例 {instanceId} 设置特定配置...");
// 使用反射设置所有可能的配置属性
var configType = appConfig.GetType();
var properties = configType.GetProperties();
foreach (var property in properties)
{
if (property.CanWrite)
{
var value = property.GetValue(appConfig);
if (value is string stringValue)
{
// 替换路径中的占位符
if (stringValue.Contains("{Instance}") ||
stringValue.Contains("{instance}"))
{
var newValue = stringValue
.Replace("{Instance}", instanceId)
.Replace("{instance}", instanceId);
property.SetValue(appConfig, newValue);
Console.WriteLine($" 更新 {property.Name}: {newValue}");
}
else if (IsPathProperty(property.Name) &&
!stringValue.Contains(instanceId))
{
// 为路径属性添加实例ID
var newValue = $"{stringValue}_Instance{instanceId}";
property.SetValue(appConfig, newValue);
Console.WriteLine($" 更新 {property.Name}: {newValue}");
}
}
else if (property.PropertyType == typeof(int) &&
IsPortProperty(property.Name))
{
// 调整端口号
var basePort = (int)value;
var newPort = basePort + (int.Parse(instanceId) - 1) * 10;
property.SetValue(appConfig, newPort);
Console.WriteLine($" 更新 {property.Name}: {newPort}");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"设置实例配置时出错: {ex.Message}");
//serilogHelper?.Info($"设置实例配置时出错: {ex.Message}");
}
}
private static bool IsPortProperty(string propertyName)
{
return propertyName.ToLower().Contains("port");
}
private static bool IsPathProperty(string propertyName)
{
return propertyName.ToLower().Contains("path") ||
propertyName.ToLower().Contains("dir") ||
propertyName.ToLower().Contains("file");
}
public static IHostBuilder CreateHostBuilder(string[] args, string instanceId) =>
Host.CreateDefaultBuilder(args)
.UseSerilog((context, config) =>
{
// 为每个实例配置独立的Serilog
config.WriteTo.Console(
outputTemplate: $"[{{Timestamp:HH:mm:ss}} {{Level:u3}}] Instance{instanceId}: {{Message:lj}}{{NewLine}}{{Exception}}")
.WriteTo.File(
path: $"./Logs/{DateTime.UtcNow:yyyy-MM-dd}/log-.txt",
rollingInterval: RollingInterval.Day,
outputTemplate: $"[{{Timestamp:yyyy-MM-dd HH:mm:ss}} {{Level:u3}}] Instance{instanceId}: {{Message:lj}}{{NewLine}}{{Exception}}");
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((context, config) =>
{
// 清除默认配置,从头开始构建
config.Sources.Clear();
// 按优先级添加配置源
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.instance{instanceId}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables("INSTANCE_")
.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel(serverOptions =>
{
Console.WriteLine(int.Parse(instanceId));
serverOptions.ListenAnyIP(1 + (int.Parse(instanceId) - 1));
});
})
.ConfigureServices((context, services) =>
{
services.AddSingleton(new InstanceInfo { Id = instanceId });
});
public class InstanceInfo
{
public string Id { get; set; } = "1";
}
private static string GetInstanceId(string[] args)
{
// 支持多种参数格式
foreach (var arg in args)
{
if (arg.StartsWith("--instance"))
{
if (arg == "--instance")
{
// 查找下一个参数作为实例ID
var index = Array.IndexOf(args, arg);
if (index + 1 < args.Length)
{
return args[index + 1];
}
}
else if (arg.StartsWith("--instance="))
{
return arg.Substring("--instance=".Length);
}
else
{
// 格式: --instance1, --instance2
return arg.Substring("--instance".Length);
}
}
}
// 如果没有指定实例ID使用随机ID避免冲突
Random random = new Random();
return random.Next(0000, 9999).ToString();
}
/// <summary>
/// CreateHostBuilder
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
// Exit事件
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
Log.Information($"系统退出,当前时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
// 释放资源
// ...
}
}
}