using Applications; using ICSharpCode.SharpZipLib.Zip; using Microsoft.Win32; using MySql.Data.MySqlClient; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Net; using System.Net.NetworkInformation; using System.Security.Cryptography; using System.Security.Principal; using System.ServiceProcess; using System.Text; using System.Text.Json; using System.Xml.Linq; class Program { static ConcurrentDictionary fileProcessMap = new(StringComparer.OrdinalIgnoreCase); static void Main(string[] args) { HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://localhost:48081/"); listener.Start(); // Console.WriteLine("Listening on http://localhost:48081/"); while (true) { var context = listener.GetContext(); ThreadPool.QueueUserWorkItem(_ => HandleRequestAsync(context)); } } static async Task HandleRequestAsync(HttpListenerContext context) { // 添加 CORS 响应头 context.Response.AddHeader("Access-Control-Allow-Origin", "*"); context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); context.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, tenant-id"); // 处理预检请求 if (context.Request.HttpMethod == "OPTIONS") { context.Response.StatusCode = (int)HttpStatusCode.OK; context.Response.Close(); return; } string path = context.Request.QueryString["path"]; string dbName = context.Request.QueryString["dbName"]; string filepath = context.Request.QueryString["filepath"]; string fileToOpen = context.Request.QueryString["file"]; string openType = context.Request.QueryString["type"]; string exePath = context.Request.QueryString["exepath"]; string workingDirectory = context.Request.QueryString["workingdirectory"]; // 生成文件夹 string folderPath = context.Request.QueryString["folderPath"]; // 文件URL string filesurl = context.Request.QueryString["filesurl"]; // 文件名称 string desiredFileName = context.Request.QueryString["filename"]; // 需要被打包的 源目录路径 string sourceDir = context.Request.QueryString["sourceDir"]; string ip = context.Request.QueryString["ip"]; string action = context.Request.Url.AbsolutePath.ToLower(); string responseMessage = ""; // 压缩文件方法 if (action == "/zipfiles") { try { if (!Directory.Exists(sourceDir)) { throw new DirectoryNotFoundException("源目录不存在!"); } // 构造ZIP文件路径(同级目录,同名.zip) string parentDir = Directory.GetParent(sourceDir).FullName; string folderName = new DirectoryInfo(sourceDir).Name; string outputZipPath = Path.Combine(parentDir, $"{folderName}.zip"); // 如果ZIP已存在,先删除(可选) if (File.Exists(outputZipPath)) { File.Delete(outputZipPath); } // 使用SharpZipLib打包 using (var zipStream = new ZipOutputStream(File.Create(outputZipPath))) { zipStream.SetLevel(5); // 压缩级别 (0-9) foreach (var file in Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories)) { string relativePath = file.Substring(sourceDir.Length + 1); var entry = new ZipEntry(relativePath) { DateTime = File.GetLastWriteTime(file), IsUnicodeText = true }; // 保留文件属性(隐藏、只读等) var fileAttributes = File.GetAttributes(file); entry.ExternalFileAttributes = (int)fileAttributes << 16; zipStream.PutNextEntry(entry); using (var fileStream = File.OpenRead(file)) { fileStream.CopyTo(zipStream); } zipStream.CloseEntry(); } } // 返回ZIP文件的绝对路径 responseMessage = Path.GetFullPath(outputZipPath); } catch (Exception ex) { throw new Exception($"压缩失败: {ex.Message}"); } } // 下载文件方法 if (action == "/downloadfiles") { try { string downloadedFilePath = await DownloadFileAsync(filesurl, folderPath); Console.WriteLine($"文件已下载到: {downloadedFilePath}"); if (IsZipFile(downloadedFilePath)) { Console.WriteLine("检测到ZIP文件,开始解压..."); string extractPath = Path.Combine(folderPath, Path.GetFileNameWithoutExtension(downloadedFilePath)); //System.IO.Compression.ZipFile.ExtractToDirectory(downloadedFilePath, folderPath); UnzipWithChineseNames(downloadedFilePath, folderPath); Console.WriteLine($"解压完成,文件保存在: {extractPath}"); // 删除原ZIP文件 File.Delete(downloadedFilePath); Console.WriteLine("已删除原ZIP文件"); } else { Console.WriteLine("文件不是ZIP格式,保留原文件"); // 获取原文件扩展名 string originalExtension = Path.GetExtension(downloadedFilePath); // 构建新文件名(保留原扩展名) string newFileName = $"{desiredFileName}{originalExtension}"; string newFilePath = Path.Combine(folderPath, newFileName); // 如果目标文件已存在,先删除 if (File.Exists(newFilePath)) { File.Delete(newFilePath); } File.Move(downloadedFilePath, newFilePath); Console.WriteLine($"文件已重命名为: {newFilePath}"); } } catch (Exception ex) { Console.WriteLine($"操作失败: {ex.Message}"); } } if (action == "/openjudgement") { string relativePath = ""; if (openType == "1") { string exeName = exePath; relativePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, exeName); } else { var startInfo = new ProcessStartInfo { FileName = exePath, WorkingDirectory = workingDirectory, // 必须! UseShellExecute = true // 或 false,根据需要 }; // 检测一下端口是否被占用48080 if (!IsPortInUse("judgement")) { Process.Start(startInfo); } } } else if (action == "/start") { if (path == "navicat") { // 启动指定服务(MySQL 服务)//需要用管理员身份启动 string serviceName = "wampmysqld"; // ← 请确认服务名 try { using (var service = new ServiceController(serviceName)) { if (service.Status != ServiceControllerStatus.Running && service.Status != ServiceControllerStatus.StartPending) { Console.WriteLine($"🟡 正在启动服务:{serviceName}..."); service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)); Console.WriteLine($"✅ 服务 {serviceName} 启动成功"); } else { Console.WriteLine($"✅ 服务 {serviceName} 已在运行中"); } } } catch (Exception ex) { Console.WriteLine($"❌ 启动服务失败:{ex.Message}"); } // 获取当前用户的 SID string userSid = WindowsIdentity.GetCurrent().User?.Value; if (userSid == null) { Console.WriteLine("❌ 无法获取当前用户 SID"); return; } string subKeyPath = $@"{userSid}\Software\PremiumSoft\Navicat\Servers\答题专用"; Console.WriteLine("当前用户 subKeyPath" + subKeyPath); try { // 打开HKEY_USERS根键 using (RegistryKey baseKey = Registry.Users) { // 创建或打开子项,写权限需要true using (RegistryKey key = baseKey.CreateSubKey(subKeyPath, true)) { if (key == null) { Console.WriteLine("❌ 无法创建或打开注册表项"); return; } // 写入键值示例 key.SetValue("Host", "localhost"); key.SetValue("Port", 6033, RegistryValueKind.DWord); key.SetValue("User", "root"); key.SetValue("Password", ""); // 注意密码如果要存可能是加密的 // 其他必要键值写入 Console.WriteLine("✅ 注册表写入成功"); } } } catch (Exception ex) { Console.WriteLine($"❌ 写入注册表失败:{ex.Message}"); } // 执行数据库创建与初始化 string connectionString = "server=localhost;port=6033;user=root;password=;charset=utf8mb4;"; try { using (var connection = new MySqlConnection(connectionString)) { connection.Open(); var createDbCmd = connection.CreateCommand(); createDbCmd.CommandText = $"CREATE DATABASE IF NOT EXISTS `{dbName}` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;"; createDbCmd.ExecuteNonQuery(); Console.WriteLine($"✅ 数据库 {dbName} 创建成功"); } string sqlScript = File.ReadAllText(filepath); using (var dbConn = new MySqlConnection(connectionString + $"database={dbName};")) { dbConn.Open(); var sqlStatements = SplitSqlStatements(sqlScript); foreach (var statement in sqlStatements) { if (string.IsNullOrWhiteSpace(statement)) continue; using var cmd = dbConn.CreateCommand(); cmd.CommandText = statement.Trim(); cmd.ExecuteNonQuery(); Console.WriteLine($"执行成功:{Truncate(statement, 80)}"); } Console.WriteLine("✅ 所有 SQL 语句执行完成,数据库初始化成功"); } } catch (Exception ex) { Console.WriteLine($"❌ 出错了:{ex.Message}"); } } try { string? resolvedPath = ResolveAppPath(path); if (!string.IsNullOrEmpty(resolvedPath) && File.Exists(resolvedPath)) { ProcessStartInfo psi = new ProcessStartInfo { FileName = resolvedPath, Arguments = string.IsNullOrEmpty(fileToOpen) ? "" : $"\"{fileToOpen}\"", UseShellExecute = true }; var process = Process.Start(psi); if (process != null) { if (!string.IsNullOrEmpty(fileToOpen)) { fileProcessMap[fileToOpen] = process.Id; responseMessage = $"Started {resolvedPath} with {fileToOpen}"; } else { responseMessage = $"Started {resolvedPath} (no file)"; } } else { responseMessage = "Failed to start process."; } } else if (!string.IsNullOrEmpty(fileToOpen) && File.Exists(fileToOpen)) { // 使用默认程序打开文件 ProcessStartInfo psi = new ProcessStartInfo { FileName = fileToOpen, UseShellExecute = true }; var process = Process.Start(psi); if (process != null) { fileProcessMap[fileToOpen] = process.Id; responseMessage = $"Opened {fileToOpen} with default program (PID: {process.Id})"; } else { responseMessage = $"Failed to open {fileToOpen}."; } } else { responseMessage = "Missing or invalid 'path' or 'file'."; } } catch (Exception ex) { responseMessage = "Error: " + ex.Message; } } else if (action == "/stop") { if (!string.IsNullOrEmpty(fileToOpen)) { if (fileProcessMap.TryRemove(fileToOpen, out int pid)) { try { var proc = Process.GetProcessById(pid); proc.Kill(); responseMessage = $"Stopped process for file: {fileToOpen} (PID: {pid})"; } catch (Exception ex) { responseMessage = $"Failed to stop process: {ex.Message}"; } } else { responseMessage = $"No tracked process for file: {fileToOpen}"; } } else { responseMessage = "Missing 'file' parameter."; } } else if (action == "/check") { string apiUrl = "http://" + ip + ":48080/admin-api/exam/app/getAppCheckList"; // ← 替换成你的接口地址 List softwareList = await FetchSoftwareListFromApi(apiUrl); List result = new List(); foreach (AppCheck softwareLine in softwareList) { var keywords = softwareLine.appName; string? resolvedPath = ResolveAppPath(keywords); if (!string.IsNullOrEmpty(resolvedPath) && File.Exists(resolvedPath)) { result.Add(keywords + ":True"); } else { result.Add(keywords + ":False"); } } // 将 result 转换为 JSON 并返回 responseMessage = JsonSerializer.Serialize(result); } else if (action == "/closeapps") { foreach (var proc in Process.GetProcesses()) { try { // 主窗口句柄不为 0,表示是一个窗口程序(用户级应用) if (proc.MainWindowHandle != IntPtr.Zero && proc.SessionId != 0 && proc.Responding) { Console.WriteLine($"App: {proc.ProcessName} (PID: {proc.Id}) - Title: {proc.MainWindowTitle}"); if (!proc.MainWindowTitle.Contains("ExamStudent") && !proc.MainWindowTitle.Contains("Applications")) { var procs = Process.GetProcessById(proc.Id); procs.Kill(); } } } catch { // 一些系统进程可能抛异常,忽略 } } } else if (action == "/allapps") { List result = new List(); foreach (var proc in Process.GetProcesses()) { try { // 主窗口句柄不为 0,表示是一个窗口程序(用户级应用) if (proc.MainWindowHandle != IntPtr.Zero && proc.SessionId != 0 && proc.Responding) { Console.WriteLine($"App: {proc.ProcessName} (PID: {proc.Id}) - Title: {proc.MainWindowTitle}"); result.Add(proc.ProcessName); } } catch { // 一些系统进程可能抛异常,忽略 } } responseMessage = JsonSerializer.Serialize(result); } try { context.Response.ContentType = "text/plain"; context.Response.ContentEncoding = System.Text.Encoding.UTF8; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(CreateJsonResponse(200, responseMessage, "") ?? "No response"); context.Response.ContentLength64 = buffer.Length; await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length); } catch (Exception ex) { Console.WriteLine("Response write error: " + ex.Message); } finally { context.Response.OutputStream.Close(); } } static string? ResolveAppPath(string appName) { var fromReg = FindInRegistry(appName); if (!string.IsNullOrEmpty(fromReg)) return fromReg; return null; } static string? FindInRegistry(string exeName) { using var regKey = Registry.ClassesRoot.OpenSubKey("Applications"); if (regKey != null) { // 获取所有子项 foreach (var subKeyName in regKey.GetSubKeyNames()) { // 打开每个应用程序子键 using var appKey = regKey.OpenSubKey(subKeyName); if (appKey != null) { // 查看是否有 "shell\open\command" 子键,这里存储着启动路径 using var commandKey = appKey.OpenSubKey(@"shell\open\command"); if (commandKey != null) { var commandValue = commandKey.GetValue("") as string; if (commandValue != null) { if (subKeyName.IndexOf(exeName, StringComparison.OrdinalIgnoreCase) >= 0) { return commandValue.Split('"')[1]; } } } } } } return null; } static async Task> FetchSoftwareListFromApi(string url) { try { using HttpClient client = new(); var response = await client.GetStringAsync(url); var apiResponse = JsonSerializer.Deserialize(response); if (apiResponse != null && apiResponse.code == 0) { // 如果 code 为 0,说明数据有效,返回 softwareList return apiResponse.data ?? new List(); } else { // Console.WriteLine($"API error: {apiResponse?.msg}"); return new List(); } } catch (Exception ex) { // Console.WriteLine("获取接口数据失败: " + ex.Message); return new List(); } } static string CreateJsonResponse(int code, T data, string msg) { var response = new StandardResponse { code = code, data = data, msg = msg }; return JsonSerializer.Serialize(response); } static string Truncate(string value, int maxLength) { if (string.IsNullOrEmpty(value)) return value; return value.Length <= maxLength ? value : value.Substring(0, maxLength) + "..."; } static List SplitSqlStatements(string sqlScript) { var statements = new List(); string delimiter = ";"; int pos = 0, lastPos = 0, length = sqlScript.Length; while (pos < length) { if (MatchKeyword(sqlScript, pos, "DELIMITER")) { string prevSegment = sqlScript.Substring(lastPos, pos - lastPos); var prevStatements = SplitByDelimiter(prevSegment, delimiter); statements.AddRange(prevStatements); int delimStart = pos + "DELIMITER".Length; while (delimStart < length && char.IsWhiteSpace(sqlScript[delimStart])) delimStart++; int delimEnd = delimStart; while (delimEnd < length && !char.IsWhiteSpace(sqlScript[delimEnd]) && sqlScript[delimEnd] != '\r' && sqlScript[delimEnd] != '\n') delimEnd++; delimiter = sqlScript.Substring(delimStart, delimEnd - delimStart); pos = delimEnd; while (pos < length && sqlScript[pos] != '\n') pos++; pos++; lastPos = pos; } else { pos++; } } if (lastPos < length) { string lastSegment = sqlScript.Substring(lastPos); var lastStatements = SplitByDelimiter(lastSegment, delimiter); statements.AddRange(lastStatements); } return statements; } static bool MatchKeyword(string text, int pos, string keyword) { if (pos + keyword.Length > text.Length) return false; var segment = text.Substring(pos, keyword.Length); return string.Equals(segment, keyword, StringComparison.OrdinalIgnoreCase); } static List SplitByDelimiter(string sql, string delimiter) { var list = new List(); int start = 0, idx; while ((idx = sql.IndexOf(delimiter, start, StringComparison.Ordinal)) >= 0) { list.Add(sql.Substring(start, idx - start)); start = idx + delimiter.Length; } if (start < sql.Length) list.Add(sql.Substring(start)); return list; } public static bool IsPortInUse(string name) { foreach (var proc in Process.GetProcesses()) { try { // 主窗口句柄不为 0,表示是一个窗口程序(用户级应用) if (proc.SessionId != 0 && proc.Responding) { if (proc.ProcessName.Contains(name)) { var procs = Process.GetProcessById(proc.Id); return true; } } } catch { // 一些系统进程可能抛异常,忽略 } } return false; // 端口可用 } /// /// 解压ZIP文件并保留中文文件名 /// /// ZIP文件路径 /// 解压目标文件夹 public static void UnzipWithChineseNames(string zipFilePath, string outputFolder) { // ✅ 注册编码提供程序(仅.NET Core / .NET 5 + 需要) Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // ✅ 设置 GBK 编码(或 UTF-8) ZipStrings.CodePage = Encoding.GetEncoding("GBK").CodePage; // 或 936 / UTF8 if (!Directory.Exists(outputFolder)) Directory.CreateDirectory(outputFolder); using (var fs = File.OpenRead(zipFilePath)) using (var zipInputStream = new ZipInputStream(fs)) { ZipEntry entry; while ((entry = zipInputStream.GetNextEntry()) != null) { // 处理路径(统一替换路径分隔符为当前系统的分隔符) string entryName = entry.Name.Replace('/', Path.DirectorySeparatorChar); string fullPath = Path.Combine(outputFolder, entryName); if (entry.IsDirectory) { // 如果是目录,确保创建该目录 if (!Directory.Exists(fullPath)) { Directory.CreateDirectory(fullPath); // 设置目录的修改时间(可选) Directory.SetLastWriteTime(fullPath, entry.DateTime); } } else { // 如果是文件,确保父目录存在 string directoryName = Path.GetDirectoryName(fullPath); if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } // 写入文件内容 using (var streamWriter = File.Create(fullPath)) { byte[] buffer = new byte[4096]; int size; while ((size = zipInputStream.Read(buffer, 0, buffer.Length)) > 0) { streamWriter.Write(buffer, 0, size); } } // 设置文件的修改时间 File.SetLastWriteTime(fullPath, entry.DateTime); } } } } static async Task DownloadFileAsync(string url, string saveDir) { using (var httpClient = new HttpClient()) { // 确保目录存在 Directory.CreateDirectory(saveDir); // 从URL获取文件名 Uri uri = new Uri(url); string fileName = Path.GetFileName(uri.LocalPath); if (string.IsNullOrEmpty(fileName)) { fileName = $"downloaded_{DateTime.Now:yyyyMMddHHmmss}"; } string fullPath = Path.Combine(saveDir, fileName); // 下载文件 var response = await httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); using (var fileStream = File.Create(fullPath)) { await response.Content.CopyToAsync(fileStream); } return fullPath; } } // 检查文件是否是ZIP格式 static bool IsZipFile(string filePath) { try { if (filePath.Contains("zip")) { return true; } else { return false; } } catch { return false; } } // 获取当前登录用户 SID static string GetCurrentUserSid() { var sid = System.Security.Principal.WindowsIdentity.GetCurrent().User?.ToString(); if (sid == null) throw new Exception("无法获取当前用户 SID"); return $"HKEY_USERS\\{sid}"; } class StandardResponse { public int code { get; set; } // 0 表示成功,其他表示失败 public T? data { get; set; } // 实际数据内容 public string msg { get; set; } = ""; // 消息提示 } }