From 902d29927e8507e52aabcdb434d8f8333872f59c Mon Sep 17 00:00:00 2001 From: PCHEN Date: Tue, 15 Sep 2026 00:06:14 +0800 Subject: [PATCH] Done --- CMakeLists.txt | 33 ++++++++++++++++++ DisableAndStopService.c | 59 +++++++++++++++++++++++++++++++ DisableAndStopService.h | 15 ++++++++ UAC.manifest | 20 +++++++++++ main.c | 77 +++++++++++++++++++++++++++++++++++++++++ resource.rc | 1 + 6 files changed, 205 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 DisableAndStopService.c create mode 100644 DisableAndStopService.h create mode 100644 UAC.manifest create mode 100644 main.c create mode 100644 resource.rc diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3a6e64e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.15) +project(CloseWindowsService C) + +file(GLOB SOURCES *.c) +list(FILTER SOURCES EXCLUDE REGEX \\.t\\.c) +list(FILTER SOURCES EXCLUDE REGEX main.c) + +foreach (item IN LISTS SOURCES) + message(STATUS "[${PROJECT_NAME}] SOURCE: ${item}") +endforeach () + +if(MSVC) + add_compile_options(/utf-8) +endif() + +if(MINGW) + # 检查项目根目录下是否存在 UAC.manifest 文件 + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/UAC.manifest") + # 自动在 build 目录下生成一个临时的资源文件资源文件 + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/uac_resource.rc" "1 24 \"${CMAKE_CURRENT_SOURCE_DIR}/UAC.manifest\"") + # 将生成的 .rc 文件作为一个源文件加入列表中 + set(UAC_RESOURCE_SRC "${CMAKE_CURRENT_BINARY_DIR}/uac_resource.rc") + else() + message(FATAL_ERROR "未找到 UAC.manifest 文件,请确保它存在于项目根目录下!") + endif() +endif() + +add_executable(${PROJECT_NAME} main.c ${SOURCES}) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR} ) + +if(MSVC) + target_link_options(${PROJECT_NAME} PRIVATE "/MANIFESTUAC:level='requireAdministrator' uiAccess='false'") +endif() \ No newline at end of file diff --git a/DisableAndStopService.c b/DisableAndStopService.c new file mode 100644 index 0000000..73eaea3 --- /dev/null +++ b/DisableAndStopService.c @@ -0,0 +1,59 @@ +#include "DisableAndStopService.h" +#include + +BOOL DisableAndStopService(const char* serviceName) +{ + SC_HANDLE hSCM = NULL; + SC_HANDLE hService = NULL; + SERVICE_STATUS_PROCESS sStatus; + DWORD dwBytesNeeded; + BOOL bResult = FALSE; + + // 1. 打开服务控制管理器 (SCM) + hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hSCM == NULL) { + printf("[-] [%s] 打开服务管理器失败 (错误码: %d)。请右键选择“以管理员身份运行”!\n", serviceName, GetLastError()); + return FALSE; + } + + // 2. 打开目标服务 (需要修改配置、停止和查询状态的权限) + hService = OpenService(hSCM, serviceName, SERVICE_CHANGE_CONFIG | SERVICE_STOP | SERVICE_QUERY_STATUS); + if (hService == NULL) { + DWORD err = GetLastError(); + if (err == ERROR_SERVICE_DOES_NOT_EXIST) { + printf("[*] [%s] 系统中不存在此服务,跳过。\n", serviceName); + } else { + printf("[-] [%s] 打开服务失败 (错误码: %d)。\n", serviceName, err); + } + CloseServiceHandle(hSCM); + return FALSE; + } + + // 3. 将启动类型修改为“禁用” (SERVICE_DISABLED) + if (ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_DISABLED, + SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { + printf("[+] [%s] 已成功设置为【禁用】。\n", serviceName); + } else { + printf("[-] [%s] 修改禁用配置失败 (错误码: %d)。\n", serviceName, GetLastError()); + } + + // 4. 检查当前运行状态,如果正在运行则发送停止信号 + if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&sStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { + if (sStatus.dwCurrentState != SERVICE_STOPPED && sStatus.dwCurrentState != SERVICE_STOP_PENDING) { + if (ControlService(hService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&sStatus)) { + printf("[+] [%s] 停止信号发送成功,服务正在关闭...\n", serviceName); + bResult = TRUE; + } else { + printf("[-] [%s] 发送停止信号失败 (错误码: %d)。\n", serviceName, GetLastError()); + } + } else { + printf("[*] [%s] 服务当前已经是停止状态。\n", serviceName); + bResult = TRUE; + } + } + + // 5. 清理句柄 + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return bResult; +} \ No newline at end of file diff --git a/DisableAndStopService.h b/DisableAndStopService.h new file mode 100644 index 0000000..8f89563 --- /dev/null +++ b/DisableAndStopService.h @@ -0,0 +1,15 @@ +#ifndef CLOSEWINDOWSSERVICE_DISABLEANDSTOPSERVICE_H +#define CLOSEWINDOWSSERVICE_DISABLEANDSTOPSERVICE_H + +#ifndef INCLUDED_WINDOWS_H +#define INCLUDED_WINDOWS_H +#include +#endif + + +BOOL DisableAndStopService(const char* serviceName); + + + + +#endif //CLOSEWINDOWSSERVICE_DISABLEANDSTOPSERVICE_H diff --git a/UAC.manifest b/UAC.manifest new file mode 100644 index 0000000..14c9746 --- /dev/null +++ b/UAC.manifest @@ -0,0 +1,20 @@ + + + + Windows Service Optimizer + + + + + + + + + + + + + + + + diff --git a/main.c b/main.c new file mode 100644 index 0000000..5d3d216 --- /dev/null +++ b/main.c @@ -0,0 +1,77 @@ +#include +#include // 需要包含此头文件来使用 IsUserAnAdmin() +#include + +int main() { + + SetConsoleOutputCP(65001); + + // 1. 检查当前是否拥有管理员权限 + if (!IsUserAnAdmin()) { + char szPath[MAX_PATH]; + // 获取当前程序自身的绝对路径 + GetModuleFileNameA(NULL, szPath, MAX_PATH); + + // 使用 "runas" 参数重新启动自身,这会强制 Windows 弹出 UAC 提权提示 + HINSTANCE hInst = ShellExecuteA(NULL, "runas", szPath, NULL, NULL, SW_SHOW); + + // 如果返回值大于 32,说明用户在弹窗中点击了“是”,新进程已成功以管理员身份拉起 + if ((INT_PTR)hInst > 32) { + return 0; // 关闭当前这个没有权限的旧进程 + } else { + // 用户点击了“否”或者关闭了弹窗 + printf("[-] 错误:此程序必须以管理员身份运行才能修改系统服务!\n"); + system("pause"); + return 1; + } + } + + // 💡 在这个数组里填入你想批量关闭的服务名称 (必须是 Service Name,非 Display Name) + const char* servicesToClose[] = { + "DiagTrack", // 微软后台遥测/用户体验收集 + "DPS", // 诊断策略服务 + "WSearch", // Windows 本地搜索索引 (不用本地搜索可关) + "TabletInputService", // 触摸键盘和手写面板服务 + "Spooler", // 打印机后台处理 (家里/公司没打印机可关) + "MapsBroker", // 下载地图管理器 (不下载离线地图可关) + "XblAuthManager", // Xbox Live 认证管理器 (不玩 Xbox 游戏可关) + "XblGameSave", // Xbox Live 游戏保存 (不玩 Xbox 游戏可关) + "dmwappushservice", // 路由设备管理中的 WAP 推送消息,本质上属于辅助遥测(隐私数据收集)的一部分 + "WHESVC", // 这是 Windows 11 较新版本中加入的后台服务,用于监控 CPU 负载、温度、电源策略等,并在变卡时记录本地跟踪数据 + "RemoteRegistry", // 允许远程用户修改本地电脑的注册表 + "RemoteAccess", // 在局域网和广域网环境中提供路由、远程连接服务 + "Fax", // 管理电脑收发传真 + "EntAppMgmtSvc", // 企业级应用合规性管理 + "WpcMonService", // 家长控制服务,用于限制儿童账户的使用时间和浏览内容 + "WerSvc", // 微软错误报告生成 (卡顿元凶之一) + "WpnService", // 微软推送通知、小组件实时刷新 + "Browser", // 局域网计算机浏览器列表 + "lmhosts", // NetBIOS 局域网历史遗留解析 + "Dosvc", // 传递优化 (后台偷偷 P2P 上传补丁吃带宽) + "WbioSrvc", // 生物识别 (无指纹/面部解锁的台式机可关) + "RetailDemo", // 线下实体店样机演示模式 + // === 小众硬件与上古僵尸服务(无设备直接关) === + "WalletService", // 微软钱包服务 + "SCardSvr", // 智能卡读卡器服务 + "ScDeviceEnum", // 智能卡设备枚举 + //"StiSvc", // 扫描仪与照相机图像输入 + "ALG", // 历史遗留的应用层网关 + "AxInstSV", // 已经淘汰的 ActiveX 插件安装服务 + }; + + // 计算数组中服务的总数量 + int totalServices = sizeof(servicesToClose) / sizeof(servicesToClose[0]); + + printf("==================================================\n"); + printf(" Windows 11 服务批量优化脚本 (C语言版) \n"); + printf("==================================================\n\n"); + + // 循环遍历数组,依次关闭服务 + for (int i = 0; i < totalServices; i++) { + DisableAndStopService(servicesToClose[i]); + } + + printf("\n所有指定服务处理完毕。\n"); + system("pause"); + return 0; +} \ No newline at end of file diff --git a/resource.rc b/resource.rc new file mode 100644 index 0000000..a8736b5 --- /dev/null +++ b/resource.rc @@ -0,0 +1 @@ +1 24 "UAC.manifest"