添加注册WindwosTerminal右键菜单工具。

This commit is contained in:
2026-02-26 09:45:25 +08:00
parent 5e34ff415b
commit c3fe31a3bf
8 changed files with 576 additions and 35 deletions

20
.clang-format Normal file
View File

@@ -0,0 +1,20 @@
BasedOnStyle: LLVM
IndentWidth: 4
PointerAlignment: Left
AccessModifierOffset: -4
ReflowComments: true
SpacesBeforeTrailingComments: 3
AllowShortFunctionsOnASingleLine: None
AllowShortEnumsOnASingleLine: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: true
AfterClass: true
TabWidth: 4
ColumnLimit: 130
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<.*>'
Priority: 1
- Regex: '^".*"'
Priority: 2

12
.clangd Normal file
View File

@@ -0,0 +1,12 @@
Hover:
ShowAKA: Yes
Diagnostics:
UnusedIncludes: None # 禁用未使用头文件提示
Suppress: [
anon_type_definition, # 禁用匿名的typedef提示
unused-variable, # 禁用未使用变量提示
unused-function, # 禁用未使用函数提示
unused-includes,
]
ClangTidy:
Remove: misc-unused-alias-decls

39
.gitignore vendored
View File

@@ -1,34 +1,5 @@
# ---> C++
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
build/
.cache/
.qtcreator/
.vs
out/

147
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,147 @@
{
"files.autoSave": "onFocusChange",
"editor.fontSize": 14,
"editor.fontFamily": "'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light'",
"editor.wordWrap": "on",
"terminal.integrated.fontFamily": "'Maple Mono NL NF CN Light'",
"cmake.configureOnOpen": true,
//"C_Cpp.intelliSenseEngine": "disabled",
"cmake.debugConfig": {
"console": "externalTerminal",
"setupCommands": [
{
"description": "-gdb-set charset utf-8",
"text": "-gdb-set charset UTF-8"
},
{
"description": "Enable gdb pretty-printing",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
//"visualizerFile": "${workspaceRoot}/.vscode/qt6.natvis",
"args": [
"uninstall"
]
},
"cmake.configureArgs": [
"-Wno-dev"
],
// "cmake.configureSettings": {
// "CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
// },
"cmake.options.statusBarVisibility": "visible",
"cmake.generator": "Ninja",
"C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json",
"C_Cpp.default.cppStandard": "c++17",
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"editor.inlayHints.enabled": "off",
"editor.unicodeHighlight.allowedLocales": {
"ja": true,
"zh-hant": true,
"zh-hans": true
},
"files.associations": {
"*.cfg": "json",
"xstring": "cpp",
"algorithm": "cpp",
"array": "cpp",
"atomic": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"condition_variable": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"forward_list": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"utility": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xmemory0": "cpp",
"xstddef": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"bit": "cpp",
"compare": "cpp",
"concepts": "cpp",
"coroutine": "cpp",
"format": "cpp",
"stop_token": "cpp",
"bitset": "cpp",
"complex": "cpp",
"cstdarg": "cpp",
"set": "cpp",
"variant": "cpp",
"expected": "cpp",
"source_location": "cpp",
"regex": "cpp",
"*.in": "cpp",
"deque": "cpp",
"future": "cpp",
"queue": "cpp",
"resumable": "cpp",
"any": "cpp",
"codecvt": "cpp",
"csignal": "cpp",
"cwctype": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"shared_mutex": "cpp",
"cinttypes": "cpp",
"cfenv": "cpp",
"unordered_set": "cpp",
"ranges": "cpp",
"typeindex": "cpp"
}
}

12
CMakeLists.txt Normal file
View File

@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.16)
project(sim_tool LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE})
if (MSVC)
add_compile_options(/utf-8)
add_subdirectory(wt_reg)
endif()

View File

@@ -1,3 +1,7 @@
# sim_tool
简易工具。
简易工具。
## wt_reg
注册Windows Terminal右键菜单的工具。

5
wt_reg/CMakeLists.txt Normal file
View File

@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(wt_reg LANGUAGES CXX)
add_executable(wt_reg main.cpp)

370
wt_reg/main.cpp Normal file
View File

@@ -0,0 +1,370 @@
/*
在包含任何 Windows 头文件之前定义宏 WIN32_LEAN_AND_MEAN
*/
#define WIN32_LEAN_AND_MEAN
#include <algorithm>
#include <filesystem>
#include <iostream>
#include <shlobj.h>
#include <string>
#include <vector>
#include <windows.h>
#ifndef WHAT_FUCK
#include <shellapi.h> // 需要在 windows.h 之后包含
#endif
namespace fs = std::filesystem;
class RegistryManager
{
private:
std::string wtPath;
bool checkWtExists()
{
if (fs::exists(wtPath) && fs::path(wtPath).filename() == "wt.exe") {
std::cout << "找到 wt.exe: " << wtPath << std::endl;
return true;
} else {
std::cout << "错误: wt.exe 不存在或路径无效: " << wtPath << std::endl;
return false;
}
}
bool isAdmin()
{
BOOL isAdmin = FALSE;
PSID adminGroup = NULL;
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
if (AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
&adminGroup)) {
if (!CheckTokenMembership(NULL, adminGroup, &isAdmin)) {
isAdmin = FALSE;
}
FreeSid(adminGroup);
}
return isAdmin != FALSE;
}
// 创建注册表键并设置值
bool createRegistryKeyWithValue(const std::string& keyPath, const std::string& valueName, const std::string& valueData)
{
HKEY hKey;
std::cout << "创建注册表键: " << keyPath << std::endl;
if (!valueName.empty()) {
std::cout << "设置值: " << valueName << " = " << valueData << std::endl;
} else {
std::cout << "设置默认值: " << valueData << std::endl;
}
LONG result =
RegCreateKeyEx(HKEY_CLASSES_ROOT, keyPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
if (result != ERROR_SUCCESS) {
std::cout << "创建注册表键失败: " << keyPath << " 错误码: " << result << std::endl;
return false;
}
if (!valueName.empty() || valueData.length() > 0) {
result = RegSetValueEx(hKey, valueName.c_str(), 0, REG_SZ, (const BYTE*)valueData.c_str(),
static_cast<DWORD>(valueData.length() + 1));
if (result != ERROR_SUCCESS) {
std::cout << "设置注册表值失败: " << valueName << " 错误码: " << result << std::endl;
RegCloseKey(hKey);
return false;
}
}
RegCloseKey(hKey);
return true;
}
// 创建注册表键(不设置值)
bool createRegistryKey(const std::string& keyPath)
{
HKEY hKey;
std::cout << "创建注册表键: " << keyPath << std::endl;
LONG result =
RegCreateKeyEx(HKEY_CLASSES_ROOT, keyPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
if (result != ERROR_SUCCESS) {
std::cout << "创建注册表键失败: " << keyPath << " 错误码: " << result << std::endl;
return false;
}
RegCloseKey(hKey);
return true;
}
// 递归删除注册表键及其所有子键
bool deleteRegistryKeyRecursive(HKEY hRoot, const std::string& subKey)
{
HKEY hKey;
// 尝试打开键
LONG result = RegOpenKeyEx(hRoot, subKey.c_str(), 0, KEY_READ | KEY_WRITE, &hKey);
if (result != ERROR_SUCCESS) {
if (result == ERROR_FILE_NOT_FOUND) {
// 键不存在,视为成功删除
return true;
}
std::cout << "打开注册表键失败: " << subKey << " 错误码: " << result << std::endl;
return false;
}
// 递归删除所有子键
DWORD subKeyCount = 0;
DWORD maxSubKeyLen = 0;
result = RegQueryInfoKey(hKey, NULL, NULL, NULL, &subKeyCount, &maxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (result == ERROR_SUCCESS && subKeyCount > 0) {
std::vector<char> subKeyName(maxSubKeyLen + 2, 0); // +2 保证有足够空间
for (DWORD i = 0; i < subKeyCount; i++) {
DWORD nameLen = maxSubKeyLen + 1;
result = RegEnumKeyEx(hKey,
0, // 总是删除第一个子键
&subKeyName[0], &nameLen, NULL, NULL, NULL, NULL);
if (result == ERROR_SUCCESS) {
std::string childPath = subKey + "\\" + std::string(&subKeyName[0]);
if (!deleteRegistryKeyRecursive(hRoot, childPath)) {
RegCloseKey(hKey);
return false;
}
} else {
RegCloseKey(hKey);
std::cout << "枚举子键失败: " << subKey << " 错误码: " << result << std::endl;
return false;
}
}
}
RegCloseKey(hKey);
// 删除当前键
result = RegDeleteKey(hRoot, subKey.c_str());
if (result != ERROR_SUCCESS) {
std::cout << "删除注册表键失败: " << subKey << " 错误码: " << result << std::endl;
return false;
}
return true;
}
bool deleteRegistryKey(const std::string& keyPath)
{
return deleteRegistryKeyRecursive(HKEY_CLASSES_ROOT, keyPath);
}
bool installContextMenu()
{
std::cout << "安装 Windows Terminal 右键菜单..." << std::endl;
bool success = true;
// 1. 创建背景右键菜单项
std::cout << "\n=== 安装背景右键菜单 ===" << std::endl;
// 1.1 创建 wt 键
if (!createRegistryKey("Directory\\Background\\shell\\wt")) {
std::cout << "创建背景菜单键失败" << std::endl;
success = false;
}
// 1.2 设置默认值
if (!createRegistryKeyWithValue("Directory\\Background\\shell\\wt", "", "Terminal")) {
std::cout << "设置背景菜单名称失败" << std::endl;
success = false;
}
// 1.3 设置图标
if (!createRegistryKeyWithValue("Directory\\Background\\shell\\wt", "Icon", "\"" + wtPath + "\"")) {
std::cout << "设置背景菜单图标失败" << std::endl;
success = false;
}
// 1.4 创建 command 子键
if (!createRegistryKey("Directory\\Background\\shell\\wt\\command")) {
std::cout << "创建背景命令键失败" << std::endl;
success = false;
}
// 1.5 设置命令
if (!createRegistryKeyWithValue("Directory\\Background\\shell\\wt\\command", "", "\"" + wtPath + "\"")) {
std::cout << "设置背景命令失败" << std::endl;
success = false;
}
// 2. 创建目录右键菜单项
std::cout << "\n=== 安装目录右键菜单 ===" << std::endl;
// 2.1 创建 wt 键
if (!createRegistryKey("Directory\\shell\\wt")) {
std::cout << "创建目录菜单键失败" << std::endl;
success = false;
}
// 2.2 设置默认值
if (!createRegistryKeyWithValue("Directory\\shell\\wt", "", "Terminal")) {
std::cout << "设置目录菜单名称失败" << std::endl;
success = false;
}
// 2.3 设置图标
if (!createRegistryKeyWithValue("Directory\\shell\\wt", "Icon", "\"" + wtPath + "\"")) {
std::cout << "设置目录菜单图标失败" << std::endl;
success = false;
}
// 2.4 创建 command 子键
if (!createRegistryKey("Directory\\shell\\wt\\command")) {
std::cout << "创建目录命令键失败" << std::endl;
success = false;
}
// 2.5 设置命令 - 注意:这里需要转义双引号
std::string command = "\"" + wtPath + "\" -d \"%V\"";
if (!createRegistryKeyWithValue("Directory\\shell\\wt\\command", "", command)) {
std::cout << "设置目录命令失败" << std::endl;
success = false;
}
return success;
}
bool uninstallContextMenu()
{
std::cout << "卸载 Windows Terminal 右键菜单..." << std::endl;
bool success = true;
// 删除背景右键菜单项
if (!deleteRegistryKey("Directory\\Background\\shell\\wt")) {
std::cout << "警告: Directory\\Background\\shell\\wt 删除失败,可能不存在或已删除" << std::endl;
}
// 删除目录右键菜单项
if (!deleteRegistryKey("Directory\\shell\\wt")) {
std::cout << "警告: Directory\\shell\\wt 删除失败,可能不存在或已删除" << std::endl;
}
return success;
}
void refreshExplorer()
{
// 发送消息刷新资源管理器
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
(LPARAM) "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", SMTO_ABORTIFHUNG, 1000,
NULL);
// 通知资源管理器更新
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
public:
RegistryManager(const std::string& path) : wtPath(path)
{
// 规范化路径(统一使用反斜杠)
std::replace(wtPath.begin(), wtPath.end(), '/', '\\');
}
bool install()
{
if (!checkWtExists()) {
return false;
}
if (!isAdmin()) {
std::cout << "需要管理员权限来修改注册表" << std::endl;
std::cout << "请以管理员身份重新运行此程序" << std::endl;
return false;
}
bool success = installContextMenu();
if (success) {
refreshExplorer();
std::cout << "\n安装成功!" << std::endl;
} else {
std::cout << "\n安装失败!" << std::endl;
}
return success;
}
bool uninstall()
{
if (!isAdmin()) {
std::cout << "需要管理员权限来修改注册表" << std::endl;
std::cout << "请以管理员身份重新运行此程序" << std::endl;
return false;
}
bool success = uninstallContextMenu();
if (success) {
refreshExplorer();
std::cout << "卸载成功!" << std::endl;
} else {
std::cout << "卸载失败!" << std::endl;
}
return success;
}
};
void printUsage(const char* programName)
{
std::cout << "Windows Terminal 右键菜单管理工具" << std::endl;
std::cout << "用法:" << std::endl;
std::cout << " " << programName << " install <wt.exe路径>" << std::endl;
std::cout << " " << programName << " uninstall" << std::endl;
std::cout << std::endl;
std::cout << "示例:" << std::endl;
std::cout << " " << programName << " install \"D:\\Program\\terminal\\wt.exe\"" << std::endl;
std::cout << " " << programName << " uninstall" << std::endl;
}
int main(int argc, char* argv[])
{
// 设置控制台输出为UTF-8
SetConsoleOutputCP(CP_UTF8);
if (argc < 2) {
printUsage(argv[0]);
return 1;
}
std::string action = argv[1];
if (action == "install") {
if (argc < 3) {
std::cout << "错误: 需要指定 wt.exe 的路径" << std::endl;
printUsage(argv[0]);
return 1;
}
std::string wtPath = argv[2];
RegistryManager manager(wtPath);
return manager.install() ? 0 : 1;
} else if (action == "uninstall") {
std::string dummyPath = "C:\\Windows\\System32\\cmd.exe";
RegistryManager manager(dummyPath);
return manager.uninstall() ? 0 : 1;
} else {
std::cout << "错误: 未知的操作: " << action << std::endl;
printUsage(argv[0]);
return 1;
}
}