mirror of
https://github.com/cmderdev/cmder.git
synced 2025-01-10 16:29:08 +08:00
Add Cmder Here
Add option to launcher to register and unregister Cmder Here
This commit is contained in:
parent
48e4046754
commit
8f6a473a40
@ -2,48 +2,107 @@
|
|||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#pragma comment(lib, "Shlwapi.lib")
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
|
||||||
#define USE_TASKBAR_API (UNICODE && _WIN32_WINNT >= _WIN32_WINNT_WIN7)
|
#ifndef UNICODE
|
||||||
|
#error "Must be compiled with unicode support."
|
||||||
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|
||||||
_In_opt_ HINSTANCE hPrevInstance,
|
|
||||||
_In_ LPTSTR lpCmdLine,
|
|
||||||
_In_ int nCmdShow)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
|
||||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
|
||||||
UNREFERENCED_PARAMETER(nCmdShow);
|
|
||||||
|
|
||||||
#if USE_TASKBAR_API
|
|
||||||
TCHAR appId[MAX_PATH] = { 0 };
|
|
||||||
#endif
|
#endif
|
||||||
TCHAR exeDir[MAX_PATH] = { 0 };
|
|
||||||
TCHAR icoPath[MAX_PATH] = { 0 };
|
#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
|
||||||
TCHAR cfgPath[MAX_PATH] = { 0 };
|
|
||||||
TCHAR conEmuPath[MAX_PATH] = { 0 };
|
#define MB_TITLE L"Cmder Launcher"
|
||||||
TCHAR args[MAX_PATH * 2 + 256] = { 0 };
|
#define SHELL_MENU_REGISTRY_PATH L"Directory\\Background\\shell\\Cmder"
|
||||||
|
|
||||||
|
#define streqi(a, b) (_wcsicmp((a), (b)) == 0)
|
||||||
|
|
||||||
|
#define WIDEN2(x) L ## x
|
||||||
|
#define WIDEN(x) WIDEN2(x)
|
||||||
|
#define __WFUNCTION__ WIDEN(__FUNCTION__)
|
||||||
|
|
||||||
|
#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }
|
||||||
|
|
||||||
|
void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
|
||||||
|
{
|
||||||
|
wchar_t * buffer;
|
||||||
|
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
|
||||||
|
{
|
||||||
|
buffer = L"Unknown error. FormatMessage failed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t message[1024];
|
||||||
|
swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
|
||||||
|
LocalFree(buffer);
|
||||||
|
|
||||||
|
MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _option
|
||||||
|
{
|
||||||
|
std::wstring name;
|
||||||
|
bool hasVal;
|
||||||
|
std::wstring value;
|
||||||
|
bool set;
|
||||||
|
} option;
|
||||||
|
|
||||||
|
typedef std::pair<std::wstring, std::wstring> optpair;
|
||||||
|
|
||||||
|
|
||||||
|
optpair GetOption()
|
||||||
|
{
|
||||||
|
wchar_t * cmd = GetCommandLine();
|
||||||
|
int argc;
|
||||||
|
wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
|
||||||
|
optpair pair;
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
pair = optpair(L"/START", L"");
|
||||||
|
}
|
||||||
|
else if (argc == 2 && argv[1][0] != L'/')
|
||||||
|
{
|
||||||
|
pair = optpair(L"/START", argv[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFree(argv);
|
||||||
|
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartCmder(std::wstring path)
|
||||||
|
{
|
||||||
|
#if USE_TASKBAR_API
|
||||||
|
wchar_t appId[MAX_PATH] = { 0 };
|
||||||
|
#endif
|
||||||
|
wchar_t exeDir[MAX_PATH] = { 0 };
|
||||||
|
wchar_t icoPath[MAX_PATH] = { 0 };
|
||||||
|
wchar_t cfgPath[MAX_PATH] = { 0 };
|
||||||
|
wchar_t conEmuPath[MAX_PATH] = { 0 };
|
||||||
|
wchar_t args[MAX_PATH * 2 + 256] = { 0 };
|
||||||
|
|
||||||
GetModuleFileName(NULL, exeDir, sizeof(exeDir));
|
GetModuleFileName(NULL, exeDir, sizeof(exeDir));
|
||||||
|
|
||||||
#if USE_TASKBAR_API
|
#if USE_TASKBAR_API
|
||||||
_tcscpy_s(appId, exeDir);
|
wcscpy_s(appId, exeDir);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PathRemoveFileSpec(exeDir);
|
PathRemoveFileSpec(exeDir);
|
||||||
|
|
||||||
PathCombine(icoPath, exeDir, _T("icons\\cmder.ico"));
|
PathCombine(icoPath, exeDir, L"icons\\cmder.ico");
|
||||||
PathCombine(cfgPath, exeDir, _T("config\\ConEmu.xml"));
|
PathCombine(cfgPath, exeDir, L"config\\ConEmu.xml");
|
||||||
PathCombine(conEmuPath, exeDir, _T("vendor\\conemu-maximus5\\ConEmu.exe"));
|
PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");
|
||||||
|
|
||||||
_tcscat_s(args, _T("/Icon \""));
|
swprintf_s(args, L"/Icon \"%s\" /Title Cmder /LoadCfgFile \"%s\"", icoPath, cfgPath);
|
||||||
_tcscat_s(args, icoPath);
|
|
||||||
_tcscat_s(args, _T("\" /Title Cmder /LoadCfgFile \""));
|
|
||||||
_tcscat_s(args, cfgPath);
|
|
||||||
_tcscat_s(args, _T("\""));
|
|
||||||
|
|
||||||
SetEnvironmentVariable(_T("CMDER_ROOT"), exeDir);
|
SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
|
||||||
|
SetEnvironmentVariable(L"CMDER_START", path.c_str());
|
||||||
|
|
||||||
STARTUPINFO si = { 0 };
|
STARTUPINFO si = { 0 };
|
||||||
si.cb = sizeof(STARTUPINFO);
|
si.cb = sizeof(STARTUPINFO);
|
||||||
@ -55,6 +114,118 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
|
CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUserOnly(std::wstring opt)
|
||||||
|
{
|
||||||
|
bool userOnly;
|
||||||
|
|
||||||
|
if (streqi(opt.c_str(), L"ALL"))
|
||||||
|
{
|
||||||
|
userOnly = false;
|
||||||
|
}
|
||||||
|
else if (streqi(opt.c_str(), L"USER"))
|
||||||
|
{
|
||||||
|
userOnly = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
HKEY GetRootKey(std::wstring opt)
|
||||||
|
{
|
||||||
|
HKEY root;
|
||||||
|
|
||||||
|
if (IsUserOnly(opt))
|
||||||
|
{
|
||||||
|
FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
|
||||||
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root = HKEY_CLASSES_ROOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterShellMenu(std::wstring opt)
|
||||||
|
{
|
||||||
|
HKEY root = GetRootKey(opt);
|
||||||
|
|
||||||
|
HKEY cmderKey;
|
||||||
|
FAIL_ON_ERROR(
|
||||||
|
RegCreateKeyEx(root, SHELL_MENU_REGISTRY_PATH, 0, NULL,
|
||||||
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
|
||||||
|
|
||||||
|
FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
|
||||||
|
FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));
|
||||||
|
|
||||||
|
HKEY command;
|
||||||
|
FAIL_ON_ERROR(
|
||||||
|
RegCreateKeyEx(cmderKey, L"command", 0, NULL,
|
||||||
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));
|
||||||
|
|
||||||
|
wchar_t exePath[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
|
GetModuleFileName(NULL, exePath, sizeof(exePath));
|
||||||
|
|
||||||
|
wchar_t commandStr[MAX_PATH + 20] = { 0 };
|
||||||
|
swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);
|
||||||
|
|
||||||
|
FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));
|
||||||
|
|
||||||
|
RegCloseKey(command);
|
||||||
|
RegCloseKey(cmderKey);
|
||||||
|
RegCloseKey(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnregisterShellMenu(std::wstring opt)
|
||||||
|
{
|
||||||
|
HKEY root = GetRootKey(opt);
|
||||||
|
HKEY cmderKey;
|
||||||
|
FAIL_ON_ERROR(
|
||||||
|
RegCreateKeyEx(root, SHELL_MENU_REGISTRY_PATH, 0, NULL,
|
||||||
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
|
||||||
|
FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
|
||||||
|
FAIL_ON_ERROR(RegDeleteKey(root, SHELL_MENU_REGISTRY_PATH));
|
||||||
|
RegCloseKey(cmderKey);
|
||||||
|
RegCloseKey(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||||
|
_In_opt_ HINSTANCE hPrevInstance,
|
||||||
|
_In_ LPTSTR lpCmdLine,
|
||||||
|
_In_ int nCmdShow)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||||
|
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||||
|
UNREFERENCED_PARAMETER(nCmdShow);
|
||||||
|
|
||||||
|
optpair opt = GetOption();
|
||||||
|
|
||||||
|
if (streqi(opt.first.c_str(), L"/START"))
|
||||||
|
{
|
||||||
|
StartCmder(opt.second);
|
||||||
|
}
|
||||||
|
else if (streqi(opt.first.c_str(), L"/REGISTER"))
|
||||||
|
{
|
||||||
|
RegisterShellMenu(opt.second);
|
||||||
|
}
|
||||||
|
else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
|
||||||
|
{
|
||||||
|
UnregisterShellMenu(opt.second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n /START <path>\n /REGISTER [USER/ALL]\n /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
3
vendor/init.bat
vendored
3
vendor/init.bat
vendored
@ -40,4 +40,7 @@
|
|||||||
|
|
||||||
:: Set home path
|
:: Set home path
|
||||||
@set HOME=%USERPROFILE%
|
@set HOME=%USERPROFILE%
|
||||||
|
|
||||||
|
@if defined CMDER_START cd /d "%CMDER_START%"
|
||||||
|
|
||||||
@echo Welcome to cmder!
|
@echo Welcome to cmder!
|
||||||
|
Loading…
Reference in New Issue
Block a user