123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- using IES.ExamServer.DI;
- using IES.ExamServer.DI.SignalRHost;
- using IES.ExamServer.Helper;
- using Microsoft.AspNetCore.Hosting.Server.Features;
- using Microsoft.AspNetCore.Hosting.Server;
- using Microsoft.AspNetCore.SpaServices;
- using Microsoft.AspNetCore.StaticFiles;
- using Microsoft.Extensions.Caching.Memory;
- using System.Text.Json;
- using System.Text.Json.Nodes;
- using VueCliMiddleware;
- using IES.ExamServer.Services;
- using System.Text;
- using IES.ExamServer.Filters;
- using IES.ExamServer.Helpers;
- using Microsoft.Extensions.Hosting;
- using System.Security.Principal;
- using Microsoft.Extensions.FileProviders;
- using System.Text.Encodings.Web;
- using System.Text.Unicode;
- using Microsoft.Extensions.Logging;
- namespace IES.ExamServer
- {
- public class Program: IDisposable
- {
- public async static Task Main(string[] args)
- {
-
- //var mutex = new Mutex(true, "IES.ExamServer", out var createdNew);
- //if (!createdNew)
- //{
- // // 防止多开,重复启动
- // Console.WriteLine("The application is already running.");
- // return;
- //}
- //ProcessHelper.CloseConhost();
- //AppDomain.CurrentDomain.ProcessExit += OnExit;
- var builder = WebApplication.CreateBuilder(args);
- string path = $"{builder.Environment.ContentRootPath}/Configs";
- //builder.WebHost.UseKestrel(options =>
- //{
- // options.ListenAnyIP(5001, listenOptions =>
- // {
- // listenOptions.UseHttps($"{path}/cert.pfx", "cdhabook") ;
- // });
- //});
- builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
- builder.Services.AddSpaStaticFiles(opt => opt.RootPath = "ClientApp/dist");
- // Add services to the container.
- builder.Services.AddControllersWithViews().AddJsonOptions(options =>
- {
- // 设置 JSON 序列化选项
- options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); // 允许所有 Unicode 字符
- options.JsonSerializerOptions.WriteIndented = true; // 格式化输出(可选)
- }); ;
- builder.Services.AddHttpClient();
- builder.Services.AddSignalR();
- builder.Services.AddHttpContextAccessor();
-
- string localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
- string dbpath = $"{localAppDataPath}\\ExamServer\\LiteDB";
- if (!System.IO.Directory.Exists(dbpath))
- {
- System.IO.Directory.CreateDirectory(dbpath);
- }
- string liteDBPath = $"Filename={dbpath}\\data.db;Connection=shared";
- var connections_LiteDB = new List<LiteDBFactoryOptions>
- {
- new LiteDBFactoryOptions { Name = "Master", Connectionstring = liteDBPath}
- };
- builder.Services.AddLiteDB(connections_LiteDB);
- builder.Services.AddMemoryCache();
- // 注册 ConnectionService 为单例
- builder.Services.AddSingleton<DataCenterConnectionService>();
- builder.Services.AddCors(options =>
- {
- options.AddDefaultPolicy(
- builder =>
- {
- builder.AllowAnyOrigin()
- .AllowAnyHeader()
- .AllowAnyMethod();
- });
- });
- builder.Services.AddMvcFilter<AuthTokenActionFilter>();
- // 添加自定义日志提供程序
- //builder.Logging.ClearProviders();
- //bool enableConsoleOutput = true;
- //builder.Logging.AddProvider(new CustomFileLoggerProvider(Path.Combine(Directory.GetCurrentDirectory(), "Logs"), enableConsoleOutput));
- // 添加日志服务
-
- var app = builder.Build();
- // Configure the HTTP request pipeline.
- if (!app.Environment.IsDevelopment())
- {
- app.UseExceptionHandler("/Home/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
- }
- else { app.UseDeveloperExceptionPage(); }
- app.UseHttpsRedirection();
- app.UseDefaultFiles();
- var contentTypeProvider = new FileExtensionContentTypeProvider();
- contentTypeProvider.Mappings[".txt"] = "text/plain";
- contentTypeProvider.Mappings[".jpg"] = "image/jpeg";
- contentTypeProvider.Mappings[".jpeg"] = "image/jpeg";
- contentTypeProvider.Mappings[".png"] = "image/png";
- contentTypeProvider.Mappings[".html"] = "text/html";
- contentTypeProvider.Mappings[".js"] = "application/javascript";
- contentTypeProvider.Mappings[".css"] = "text/css";
- contentTypeProvider.Mappings[".mp4"] = "video/mp4";
- contentTypeProvider.Mappings[".mp3"] = "audio/mpeg";
- contentTypeProvider.Mappings[".json"] = "application/json";
- contentTypeProvider.Mappings[".pdf"] = "application/pdf";
- string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
- if (!Directory.Exists(packagePath))
- {
- Directory.CreateDirectory(packagePath);
- }
- app.UseStaticFiles(new StaticFileOptions
- {
- FileProvider = new PhysicalFileProvider(
- Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package")),
- RequestPath = "/package",
- ContentTypeProvider = contentTypeProvider,
- });
- app.UseRouting();
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapHub<SignalRExamServerHub>("/signalr/exam").RequireCors("any");
- endpoints.MapControllers();
- // NOTE: VueCliProxy is meant for developement and hot module reload
- // NOTE: SSR has not been tested
- // Production systems should only need the UseSpaStaticFiles() (above)
- // You could wrap this proxy in either
- // if (System.Diagnostics.Debugger.IsAttached)
- // or a preprocessor such as #if DEBUG
- /*
- npm install -g @vue
- vue create app
- */
- //#if DEBUG
- endpoints.MapToVueCliProxy(
- "{*path}",
- new SpaOptions { SourcePath = "ClientApp" },
- npmScript: (System.Diagnostics.Debugger.IsAttached) ? "serve" : null,
- // regex: "Compiled successfully",
- forceKill: true
- );
- //#else
- // endpoints.MapFallbackToFile("index.html");
- //#endif
- });
- IMemoryCache? cache = app.Services.GetRequiredService<IMemoryCache>();
- IHttpClientFactory? clientFactory = app.Services.GetRequiredService<IHttpClientFactory>();
- LiteDBFactory liteDBFactory = app.Services.GetRequiredService<LiteDBFactory>();
- JsonNode? data = null;
- int hybrid = 0;
- string remote = "127.0.0.1";
- string region = "局域网·内网";
- try
- {
- string? CenterUrl = builder.Configuration.GetValue<string>("ExamServer:CenterUrl");
- var httpclient = clientFactory.CreateClient();
- httpclient.Timeout= TimeSpan.FromSeconds(10);
- HttpResponseMessage message = await httpclient.PostAsJsonAsync($"{CenterUrl}/core/system-info", new { });
- if (message.IsSuccessStatusCode)
- {
- string content = await message.Content.ReadAsStringAsync();
- data = JsonSerializer.Deserialize<JsonNode>(content);
- data!["centerUrl"]=CenterUrl;
- cache.Set(Constant._KeyServerCenter, data);
- remote=$"{data["ip"]}";
- region=$"{data["region"]}";
- hybrid =1;
- }
- }
- catch (Exception ex)
- {
- //云端服务连接失败
- hybrid = 0;
- }
- //单例模式存储云端数据中心连接状态
- DataCenterConnectionService connectionService= app.Services.GetRequiredService<DataCenterConnectionService>();
- connectionService.centerUrl = hybrid == 1 ? $"{data?["centerUrl"]}" : null;
- connectionService.dataCenterIsConnected = hybrid==1 ? true : false;
- var lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>();
- lifetime.ApplicationStarted.Register(() =>
- {
-
- var server = app.Services.GetService<IServer>();
- var logger = app.Services.GetRequiredService<ILogger<Program>>();
- var d = server?.Features.Get<IServerAddressesFeature>();
- IEnumerable<string>? _url = server?.Features.Get<IServerAddressesFeature>()?.Addresses;
- ServerDevice serverDevice = IndexService.GetServerDevice(remote, region, _url);
- //int domainStatus =0;
- //string domain = builder.Configuration.GetValue<string>("ExamClient:Domain");
- //foreach (var network in serverDevice.networks)
- //{
- // try
- // {
- // string domain_entry = $"{network.ip} {domain}";
- // string hostsFilePath = @"C:\Windows\System32\drivers\etc\hosts";
- // string content = File.ReadAllText(hostsFilePath, Encoding.UTF8);
- // if (!content.Contains(domain_entry))
- // {
- // content += Environment.NewLine + domain_entry;
- // // 使用管理员权限运行此程序,不然会抛出UnauthorizedAccessException
- // File.WriteAllText(hostsFilePath, content, Encoding.UTF8);
- // domainStatus=1;
- // // Console.WriteLine("Hosts file updated successfully.");
- // }
- // else
- // {
- // domainStatus=1;
- // //Console.WriteLine("The entry already exists in the hosts file.");
- // }
- // }
- // catch (UnauthorizedAccessException)
- // {
- // domainStatus=2;
- // // Console.WriteLine("You need to run this program with administrative privileges to modify the hosts file.");
- // }
- // catch (Exception ex)
- // {
- // domainStatus=0;
- // // Console.WriteLine($"An error occurred: {ex.Message}");
- // }
- //}
- //serverDevice.domainStatus=domainStatus;
- //serverDevice.domain=domain;
- logger.LogInformation($"服务端设备信息:{JsonSerializer.Serialize(serverDevice,options: new JsonSerializerOptions { Encoder =JavaScriptEncoder.Create(UnicodeRanges.All)})}");
- cache.Set(Constant._KeyServerDevice, serverDevice);
- });
- // 退出程序
- lifetime.ApplicationStopping.Register(() =>
- {
- Console.WriteLine("The application is stopping. Performing cleanup...");
- // 在这里添加清理资源、保存数据等逻辑
- });
- app.MapGet("/hello", (ILogger<Program> logger) =>
- {
- logger.LogInformation("This is an information log.");
- logger.LogError("This is an error log.");
- var data = new { Id = 123, Name = "Test Data服务端设备信息" };
- logger.LogData(data, data.Id.ToString());
- return "Hello World!";
- });
- await app.RunAsync();
- }
- //static void OnExit(object sender, EventArgs e)
- //{
- // Console.WriteLine("正在退出程序...");
- // // 执行任何需要的清理工作
- // // 例如: 保存状态,关闭文件和数据库连接等
- // // 通过调用 Environment.Exit 来结束进程
- // Environment.Exit(0);
- //}
- public void Dispose()
- {
- // 清理代码
- //Console.WriteLine("正在退出...");
- // 释放资源、关闭连接等
- }
- }
- public class SystemInfo
- {
- public string? id { get; set; }
- public string? version { get; set; }
- public string? description { get; set; }
- public long nowtime { get; set; }
- public string? region { get; set; }
- public string? ip { get; set; }
- public string? date { get; set; }
- public string? centerUrl { get; set; }
- }
- }
|