mirror of
https://gitea.tendokyu.moe/moegrid/sega-mount.git
synced 2026-09-22 22:37:57 +03:00
修复日志不打印到GUI的问题,添加UAC
This commit is contained in:
+3
-1
@@ -73,7 +73,9 @@ target_include_directories(sega_mount PRIVATE src res)
|
||||
if (WIN32)
|
||||
target_link_libraries(sega_mount PRIVATE ${SEGA_WIN_LIBS} imgui comdlg32)
|
||||
# WinMain 入口需要 Windows 子系统(无参数时不弹控制台窗口)
|
||||
set_target_properties(sega_mount PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
|
||||
# manifest 请求管理员权限(UAC 提权)
|
||||
set_target_properties(sega_mount PROPERTIES LINK_FLAGS
|
||||
"/SUBSYSTEM:WINDOWS /MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\"")
|
||||
endif ()
|
||||
set_target_properties(sega_mount PROPERTIES OUTPUT_NAME sega_mount)
|
||||
|
||||
|
||||
+62
-4
@@ -84,10 +84,68 @@ namespace driver {
|
||||
if (!StartServiceW(hSvc, 0, nullptr)) {
|
||||
DWORD last = GetLastError();
|
||||
if (last != ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
if (error) *error = "StartService 失败:" + utils::last_error_str(last);
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return false;
|
||||
// 文件不存在(旧服务路径失效):删除旧服务,重新提取驱动并创建
|
||||
if (last == ERROR_FILE_NOT_FOUND) {
|
||||
LOG_INFO("服务路径失效,重新安装驱动");
|
||||
CloseServiceHandle(hSvc);
|
||||
hSvc = nullptr;
|
||||
|
||||
// 删除旧服务
|
||||
hSvc = OpenServiceW(hScm, SERVICE_NAME, SERVICE_ALL_ACCESS | DELETE);
|
||||
if (hSvc) {
|
||||
DeleteService(hSvc);
|
||||
CloseServiceHandle(hSvc);
|
||||
hSvc = nullptr;
|
||||
}
|
||||
|
||||
// 重新提取驱动到系统目录
|
||||
wchar_t sys_dir2[MAX_PATH] = {};
|
||||
UINT sys_len2 = GetSystemDirectoryW(sys_dir2, MAX_PATH);
|
||||
if (sys_len2 == 0 || sys_len2 > MAX_PATH) {
|
||||
if (error) *error = "GetSystemDirectory 失败:" + utils::last_error_str();
|
||||
CloseServiceHandle(hScm);
|
||||
return false;
|
||||
}
|
||||
std::wstring dst_path2 = std::wstring(sys_dir2) + L"\\drivers\\" + DRIVER_FILENAME;
|
||||
if (!utils::extract_resource_to_file(IDR_DRIVER_SYS, dst_path2, error)) {
|
||||
CloseServiceHandle(hScm);
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("驱动已提取到 {}", utils::wstr_to_str(dst_path2));
|
||||
|
||||
// 重新创建服务
|
||||
hSvc = CreateServiceW(
|
||||
hScm, SERVICE_NAME, SERVICE_NAME,
|
||||
SERVICE_ALL_ACCESS,
|
||||
SERVICE_KERNEL_DRIVER,
|
||||
SERVICE_DEMAND_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
dst_path2.c_str(),
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr
|
||||
);
|
||||
if (!hSvc) {
|
||||
if (error) *error = "CreateService 失败:" + utils::last_error_str();
|
||||
CloseServiceHandle(hScm);
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("服务已重新安装:{}", utils::wstr_to_str(dst_path2));
|
||||
|
||||
// 再次尝试启动
|
||||
if (!StartServiceW(hSvc, 0, nullptr)) {
|
||||
DWORD last2 = GetLastError();
|
||||
if (last2 != ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
if (error) *error = "StartService 失败:" + utils::last_error_str(last2);
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (error) *error = "StartService 失败:" + utils::last_error_str(last);
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ inline bool g_unmounting = false;
|
||||
inline std::vector<std::string> g_log_lines;
|
||||
inline std::mutex g_log_mutex;
|
||||
inline bool g_auto_scroll = true;
|
||||
inline bool g_log_capture_enabled = false;
|
||||
|
||||
// ===== DX11 全局变量 =====
|
||||
inline ID3D11Device *g_pd3dDevice = nullptr;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#define LOG_MODULE "GUI"
|
||||
#include "gui_utils.h"
|
||||
#include "gui_common.h"
|
||||
#include "config.h"
|
||||
#include "utils/strings.h"
|
||||
#include "utils/log.h"
|
||||
#include <windows.h>
|
||||
#include <commdlg.h>
|
||||
#include <shlobj.h>
|
||||
@@ -12,9 +14,9 @@ void load_config_file(const std::wstring &path) {
|
||||
g_config_path = utils::wstr_to_str(path);
|
||||
std::string err;
|
||||
if (parse_config(path, g_cfg, &err)) {
|
||||
g_log_lines.push_back(std::format("[INFO] 配置已加载:{}", g_config_path));
|
||||
LOG_INFO("配置已加载:{}", g_config_path);
|
||||
} else {
|
||||
g_log_lines.push_back(std::format("[ERROR] {}", err));
|
||||
LOG_ERROR("{}", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-12
@@ -1,3 +1,4 @@
|
||||
#define LOG_MODULE "UI"
|
||||
#include "ui.h"
|
||||
#include "gui_common.h"
|
||||
#include "gui_utils.h"
|
||||
@@ -6,13 +7,19 @@
|
||||
#include "resource.h"
|
||||
#include "utils/resource.h"
|
||||
#include "utils/strings.h"
|
||||
#include "utils/log.h"
|
||||
#include "imgui.h"
|
||||
#include "icons/lucide.h"
|
||||
#include <format>
|
||||
#include <windows.h>
|
||||
|
||||
// 初始化 ImGui:主题、DPI 缩放、字体加载
|
||||
// 初始化 ImGui:主题、DPI 缩放、字体加载、日志捕获
|
||||
void InitUI(float main_scale) {
|
||||
// 注册日志 sink:将 LOG_XXX 输出同步到 GUI 日志面板
|
||||
logger::set_sink([](logger::Level level, const std::string &line) {
|
||||
std::lock_guard<std::mutex> lock(g_log_mutex);
|
||||
g_log_lines.push_back(line);
|
||||
});
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
@@ -82,7 +89,7 @@ void DrawUI() {
|
||||
g_config_path_w = utils::to_wstring(g_config_path);
|
||||
std::string err;
|
||||
save_config(g_config_path_w, g_cfg, &err);
|
||||
g_log_lines.emplace_back("[INFO] 配置已保存");
|
||||
LOG_INFO("配置已保存");
|
||||
}
|
||||
|
||||
// 主题切换按钮
|
||||
@@ -233,13 +240,12 @@ void DrawUI() {
|
||||
if (ImGui::Button(g_driver_ready ? (ICON_PLAY " 挂载") : (ICON_CIRCLE_ALERT " 挂载(需要驱动)"))) {
|
||||
if (g_driver_ready && !g_mounting) {
|
||||
g_mounting = true;
|
||||
g_log_lines.emplace_back("[INFO] 开始挂载...");
|
||||
LOG_INFO("开始挂载...");
|
||||
auto result = icf_mount::mount_icf_apps(g_cfg);
|
||||
if (result.success) {
|
||||
g_log_lines.push_back(std::format("[INFO] 挂载成功:{} 个 APP,{} 个 OPT",
|
||||
result.apps.size(), result.opts.size()));
|
||||
LOG_INFO("挂载成功:{} 个 APP,{} 个 OPT", result.apps.size(), result.opts.size());
|
||||
} else {
|
||||
g_log_lines.push_back(std::format("[ERROR] 挂载失败:{}", result.error));
|
||||
LOG_ERROR("挂载失败:{}", result.error);
|
||||
}
|
||||
g_mounting = false;
|
||||
}
|
||||
@@ -249,13 +255,12 @@ void DrawUI() {
|
||||
if (ImGui::Button(ICON_SQUARE " 卸载")) {
|
||||
if (g_driver_ready && !g_unmounting) {
|
||||
g_unmounting = true;
|
||||
g_log_lines.emplace_back("[INFO] 开始卸载...");
|
||||
LOG_INFO("开始卸载...");
|
||||
auto result = icf_mount::unmount_icf_apps(g_cfg);
|
||||
if (result.success) {
|
||||
g_log_lines.push_back(std::format("[INFO] 卸载成功:{} 个 APP,{} 个 OPT",
|
||||
result.apps.size(), result.opts.size()));
|
||||
LOG_INFO("卸载成功:{} 个 APP,{} 个 OPT", result.apps.size(), result.opts.size());
|
||||
} else {
|
||||
g_log_lines.push_back(std::format("[ERROR] 卸载失败:{}", result.error));
|
||||
LOG_ERROR("卸载失败:{}", result.error);
|
||||
}
|
||||
g_unmounting = false;
|
||||
}
|
||||
@@ -271,11 +276,11 @@ void DrawUI() {
|
||||
|
||||
ImGui::BeginChild("LogPanel", ImVec2(-1, -1), ImGuiChildFlags_Borders);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_log_mutex);
|
||||
std::lock_guard lock(g_log_mutex);
|
||||
for (const auto &line: g_log_lines) {
|
||||
if (line.find("[ERROR]") != std::string::npos)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.3f, 0.3f, 1.0f));
|
||||
else if (line.find("[WARN]") != std::string::npos)
|
||||
else if (line.find("[WARN ") != std::string::npos || line.find("[WARN]") != std::string::npos)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.2f, 1.0f));
|
||||
else
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 0.7f, 0.7f, 1.0f));
|
||||
|
||||
+2
-1
@@ -191,6 +191,7 @@ namespace icf_mount {
|
||||
|
||||
if (!mount_res.success) {
|
||||
LOG_ERROR("挂载 OPT {} 失败:{}", entry->version, mount_res.error);
|
||||
all_ok = false;
|
||||
}
|
||||
|
||||
result.opts.push_back(mount_entry);
|
||||
@@ -222,7 +223,7 @@ namespace icf_mount {
|
||||
|
||||
result.success = all_ok;
|
||||
if (!all_ok) {
|
||||
result.error = "部分 APP 挂载失败";
|
||||
result.error = "部分容器挂载失败,详见日志";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+2
-6
@@ -146,9 +146,9 @@ static int run_gui(HINSTANCE hInstance) {
|
||||
std::string svc_err;
|
||||
g_driver_ready = driver::ensure_running(&svc_err);
|
||||
if (g_driver_ready)
|
||||
g_log_lines.emplace_back("[INFO] 驱动服务已就绪");
|
||||
LOG_INFO("驱动服务已就绪");
|
||||
else
|
||||
g_log_lines.push_back(std::format("[ERROR] 驱动:{}", svc_err));
|
||||
LOG_ERROR("驱动:{}", svc_err);
|
||||
}
|
||||
|
||||
// 初始化 ImGui DPI 感知
|
||||
@@ -186,9 +186,6 @@ static int run_gui(HINSTANCE hInstance) {
|
||||
ImGui_ImplWin32_Init(hwnd);
|
||||
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
|
||||
|
||||
// 启用日志捕获
|
||||
g_log_capture_enabled = true;
|
||||
|
||||
// 主循环
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
@@ -247,7 +244,6 @@ static int run_gui(HINSTANCE hInstance) {
|
||||
}
|
||||
|
||||
// 清理
|
||||
g_log_capture_enabled = false;
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
+18
-10
@@ -6,6 +6,9 @@ namespace logger {
|
||||
// 全局最低输出等级
|
||||
static auto g_min_level = Level::Debug;
|
||||
|
||||
// 日志 sink 回调
|
||||
static LogSink g_sink = nullptr;
|
||||
|
||||
// 等级对应的标签文字(固定5字符宽度对齐)
|
||||
static const char *level_tag(Level level) {
|
||||
switch (level) {
|
||||
@@ -32,11 +35,19 @@ namespace logger {
|
||||
g_min_level = level;
|
||||
}
|
||||
|
||||
void set_sink(LogSink sink) {
|
||||
g_sink = std::move(sink);
|
||||
}
|
||||
|
||||
void output_raw(Level level, const char *module, const std::string &message) {
|
||||
if (static_cast<int>(level) < static_cast<int>(g_min_level)) return;
|
||||
|
||||
// 组装完整日志行: [LEVEL][MODULE] message
|
||||
std::string line = std::string("[") + level_tag(level) + "][" + module + "] " + message;
|
||||
|
||||
// 控制台输出
|
||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
WORD orig_attr = 7; // 默认灰白
|
||||
WORD orig_attr = 7;
|
||||
if (hStdout != INVALID_HANDLE_VALUE) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi{};
|
||||
if (GetConsoleScreenBufferInfo(hStdout, &csbi)) {
|
||||
@@ -44,19 +55,16 @@ namespace logger {
|
||||
}
|
||||
SetConsoleTextAttribute(hStdout, level_color(level));
|
||||
}
|
||||
|
||||
// 输出: [LEVEL][MODULE] message\n
|
||||
std::fputs("[", stdout);
|
||||
std::fputs(level_tag(level), stdout);
|
||||
std::fputs("][", stdout);
|
||||
std::fputs(module, stdout);
|
||||
std::fputs("] ", stdout);
|
||||
std::fputs(message.c_str(), stdout);
|
||||
std::fputs(line.c_str(), stdout);
|
||||
std::fputc('\n', stdout);
|
||||
std::fflush(stdout);
|
||||
|
||||
if (hStdout != INVALID_HANDLE_VALUE) {
|
||||
SetConsoleTextAttribute(hStdout, orig_attr);
|
||||
}
|
||||
|
||||
// sink 回调(GUI 捕获)
|
||||
if (g_sink) {
|
||||
g_sink(level, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <format>
|
||||
#include <functional>
|
||||
|
||||
namespace logger {
|
||||
// 日志等级
|
||||
@@ -12,9 +13,15 @@ namespace logger {
|
||||
Error
|
||||
};
|
||||
|
||||
// 日志 sink 回调类型:接收完整格式化行 "[LEVEL][MODULE] message"
|
||||
using LogSink = std::function<void(Level level, const std::string &line)>;
|
||||
|
||||
// 设置全局最低输出等级(低于此等级的日志不输出),默认 Debug(全部输出)
|
||||
void set_min_level(Level level);
|
||||
|
||||
// 设置日志 sink 回调(传入 nullptr 取消),每次输出时会额外调用
|
||||
void set_sink(LogSink sink);
|
||||
|
||||
// 原始字符串输出(已格式化完成),带模块名
|
||||
void output_raw(Level level, const char *module, const std::string &message);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user