项目初次提交

This commit is contained in:
YOHO\20373
2025-06-27 11:51:40 +08:00
commit fb9891168a
106 changed files with 3404 additions and 0 deletions

510
Applications/Program.cs Normal file
View File

@@ -0,0 +1,510 @@
using Applications;
using Microsoft.Win32;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net;
using System.Security.Cryptography;
using System.Text.Json;
using System.Xml.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using MySql.Data.MySqlClient;
using System.Security.Principal;
using System.ServiceProcess;
class Program
{
static ConcurrentDictionary<string, int> 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");
// 处理预检请求
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 ip = context.Request.QueryString["ip"];
string action = context.Request.Url.AbsolutePath.ToLower();
string responseMessage = "";
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<AppCheck> softwareList = await FetchSoftwareListFromApi(apiUrl);
List<string> result = new List<string>();
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<string> result = new List<string>();
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<List<AppCheck>> FetchSoftwareListFromApi(string url)
{
try
{
using HttpClient client = new();
var response = await client.GetStringAsync(url);
var apiResponse = JsonSerializer.Deserialize<ApiResponse>(response);
if (apiResponse != null && apiResponse.code == 0)
{
// 如果 code 为 0说明数据有效返回 softwareList
return apiResponse.data ?? new List<AppCheck>();
}
else
{
// Console.WriteLine($"API error: {apiResponse?.msg}");
return new List<AppCheck>();
}
}
catch (Exception ex)
{
// Console.WriteLine("获取接口数据失败: " + ex.Message);
return new List<AppCheck>();
}
}
static string CreateJsonResponse<T>(int code, T data, string msg)
{
var response = new StandardResponse<T>
{
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<string> SplitSqlStatements(string sqlScript)
{
var statements = new List<string>();
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<string> SplitByDelimiter(string sql, string delimiter)
{
var list = new List<string>();
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;
}
// 获取当前登录用户 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<T>
{
public int code { get; set; } // 0 表示成功,其他表示失败
public T? data { get; set; } // 实际数据内容
public string msg { get; set; } = ""; // 消息提示
}
}