/
sevawhite
/
claude-code-installer
Обзор
Документация
Войти
/
sevawhite
/
claude-code-installer
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
installer.cpp.backup
565 строк
20 KB
Seva
Initial commit: Claude Code Installer with modern design
24 июл 2026, 16:08
24 июл 2026, 16:08
726c2dd
Код
Авторство
О чём код?
/* * Claude Code Installer for Windows * GUI Installer using Windows API */ #include <windows.h> #include <commctrl.h> #include <shlobj.h> #include <string> #include <fstream> #include <direct.h> #pragma comment(lib, "comctl32.lib") #pragma comment(lib, "shell32.lib") // Глобальные переменные HINSTANCE hInst; HWND hwndMain; int currentPage = 0; const int TOTAL_PAGES = 7; // Данные установки struct InstallData { std::string installPath; std::string apiKey; bool useProxy; std::string proxyIp; std::string proxyPort; std::string proxyLogin; std::string proxyPassword; std::string telegramToken; } installData; // ID элементов управления #define IDC_NEXT 1001 #define IDC_BACK 1002 #define IDC_CANCEL 1003 #define IDC_INSTALL_PATH 1004 #define IDC_BROWSE 1005 #define IDC_API_KEY 1006 #define IDC_USE_PROXY 1007 #define IDC_PROXY_IP 1008 #define IDC_PROXY_PORT 1009 #define IDC_PROXY_LOGIN 1010 #define IDC_PROXY_PASSWORD 1011 #define IDC_TELEGRAM_TOKEN 1012 #define IDC_PROGRESS 1013 #define IDC_LOG 1014 // Вспомогательные функции std::string GetUserProfilePath() { char path[MAX_PATH]; if (SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, path) == S_OK) { return std::string(path); } return "C:\\Users\\Default"; } void CreateDirectoryRecursive(const std::string& path) { size_t pos = 0; do { pos = path.find_first_of("\\/", pos + 1); std::string subPath = path.substr(0, pos); CreateDirectoryA(subPath.c_str(), NULL); } while (pos != std::string::npos); } void SaveConfig() { std::string configPath = installData.installPath + "\\config.json"; std::ofstream file(configPath); file << "{\n"; file << " \"api_key\": \"" << installData.apiKey << "\",\n"; file << " \"telegram_token\": \"" << installData.telegramToken << "\",\n"; file << " \"proxy\": {\n"; file << " \"enabled\": " << (installData.useProxy ? "true" : "false") << ",\n"; file << " \"ip\": \"" << installData.proxyIp << "\",\n"; file << " \"port\": \"" << installData.proxyPort << "\",\n"; file << " \"login\": \"" << installData.proxyLogin << "\",\n"; file << " \"password\": \"" << installData.proxyPassword << "\"\n"; file << " }\n"; file << "}\n"; file.close(); } void CreateLaunchScript() { std::string scriptPath = installData.installPath + "\\start-claude.bat"; std::ofstream file(scriptPath); file << "@echo off\n"; file << "chcp 65001 >nul\n"; file << "title Claude Code Launcher\n\n"; file << "echo ========================================\n"; file << "echo Claude Code Launcher\n"; file << "echo ========================================\n"; file << "echo.\n\n"; if (!installData.apiKey.empty()) { file << "set ANTHROPIC_API_KEY=" << installData.apiKey << "\n"; } file << "set ANTHROPIC_BASE_URL=http://localhost:20128/v1\n"; file << "set ANTHROPIC_MODEL=kr/claude-sonnet-4.5\n\n"; if (installData.useProxy) { file << "set HTTP_PROXY=http://" << installData.proxyLogin << ":" << installData.proxyPassword << "@" << installData.proxyIp << ":" << installData.proxyPort << "\n"; file << "set HTTPS_PROXY=http://" << installData.proxyLogin << ":" << installData.proxyPassword << "@" << installData.proxyIp << ":" << installData.proxyPort << "\n"; file << "set NO_PROXY=localhost,127.0.0.1\n\n"; } file << "echo Запуск Claude Code...\n"; file << "echo.\n\n"; file << "set \"CLAUDE_EXE=" << installData.installPath << "\\claude\\claude.exe\"\n\n"; file << "if exist \"%CLAUDE_EXE%\" (\n"; file << " echo Найден: %CLAUDE_EXE%\n"; file << " \"%CLAUDE_EXE%\" --channels plugin:telegram@claude-plugins-official\n"; file << ") else (\n"; file << " echo ОШИБКА: claude.exe не найден!\n"; file << " echo Скачайте: https://disk.yandex.ru/d/bjIN_6e2j94LhA\n"; file << " pause\n"; file << ")\n"; file.close(); } // Функции отрисовки страниц void ShowPage(HWND hwnd, int page); void DrawWelcomePage(HWND hwnd) { HWND hStatic; hStatic = CreateWindowW(L"STATIC", L"Добро пожаловать в установщик Claude Code!\n\n" L"Этот мастер поможет установить:\n" L"• Node.js 22 LTS\n" L"• Claude Code CLI\n" L"• OmniRoute маршрутизатор\n" L"• Telegram интеграция\n\n" L"Нажмите 'Далее' для продолжения.", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 100, 600, 250, hwnd, NULL, hInst, NULL); HFONT hFont = CreateFontW(18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Segoe UI"); SendMessage(hStatic, WM_SETFONT, (WPARAM)hFont, TRUE); } void DrawInstallPathPage(HWND hwnd) { CreateWindowW(L"STATIC", L"Папка установки:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 100, 200, 25, hwnd, NULL, hInst, NULL); std::wstring wPath(installData.installPath.begin(), installData.installPath.end()); CreateWindowW(L"EDIT", wPath.c_str(), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 50, 130, 500, 25, hwnd, (HMENU)IDC_INSTALL_PATH, hInst, NULL); CreateWindowW(L"BUTTON", L"Обзор...", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 560, 130, 90, 25, hwnd, (HMENU)IDC_BROWSE, hInst, NULL); } void DrawOmniRoutePage(HWND hwnd) { CreateWindowW(L"STATIC", L"Введите API ключ от OmniRoute:\n\n" L"Как получить:\n" L"1. Запустите 'omniroute'\n" L"2. Зарегистрируйтесь в веб-интерфейсе\n" L"3. Создайте API ключ\n\n" L"Можно пропустить и настроить позже.", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 80, 600, 150, hwnd, NULL, hInst, NULL); CreateWindowW(L"STATIC", L"API ключ:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 240, 200, 25, hwnd, NULL, hInst, NULL); CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_PASSWORD, 50, 265, 600, 25, hwnd, (HMENU)IDC_API_KEY, hInst, NULL); } void DrawProxyPage(HWND hwnd) { CreateWindowW(L"STATIC", L"Настройка прокси (опционально)\n\n" L"Если используете VPN - пропустите этот шаг", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 80, 600, 60, hwnd, NULL, hInst, NULL); CreateWindowW(L"BUTTON", L"Использовать прокси", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 50, 150, 200, 25, hwnd, (HMENU)IDC_USE_PROXY, hInst, NULL); CreateWindowW(L"STATIC", L"IP адрес:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 190, 100, 25, hwnd, NULL, hInst, NULL); CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 160, 190, 200, 25, hwnd, (HMENU)IDC_PROXY_IP, hInst, NULL); CreateWindowW(L"STATIC", L"Порт:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 225, 100, 25, hwnd, NULL, hInst, NULL); CreateWindowW(L"EDIT", L"8080", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 160, 225, 200, 25, hwnd, (HMENU)IDC_PROXY_PORT, hInst, NULL); CreateWindowW(L"STATIC", L"Логин:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 260, 100, 25, hwnd, NULL, hInst, NULL); CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 160, 260, 200, 25, hwnd, (HMENU)IDC_PROXY_LOGIN, hInst, NULL); CreateWindowW(L"STATIC", L"Пароль:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 295, 100, 25, hwnd, NULL, hInst, NULL); CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_PASSWORD, 160, 295, 200, 25, hwnd, (HMENU)IDC_PROXY_PASSWORD, hInst, NULL); } void DrawTelegramPage(HWND hwnd) { CreateWindowW(L"STATIC", L"Telegram интеграция (опционально)\n\n" L"Как создать бота:\n" L"1. Откройте @BotFather в Telegram\n" L"2. Отправьте: /newbot\n" L"3. Следуйте инструкциям\n" L"4. Скопируйте токен\n\n" L"Можно пропустить и настроить позже.", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 80, 600, 180, hwnd, NULL, hInst, NULL); CreateWindowW(L"STATIC", L"Telegram Token:", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 270, 200, 25, hwnd, NULL, hInst, NULL); CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 50, 295, 600, 25, hwnd, (HMENU)IDC_TELEGRAM_TOKEN, hInst, NULL); } void DrawSummaryPage(HWND hwnd) { std::wstring summary = L"Готово к установке!\n\n"; summary += L"Папка: "; summary += std::wstring(installData.installPath.begin(), installData.installPath.end()); summary += L"\n"; summary += L"API ключ: "; summary += installData.apiKey.empty() ? L"Не настроен" : L"Настроен"; summary += L"\n"; summary += L"Прокси: "; summary += installData.useProxy ? L"Включен" : L"Выключен"; summary += L"\n"; summary += L"Telegram: "; summary += installData.telegramToken.empty() ? L"Не настроен" : L"Настроен"; summary += L"\n\n"; summary += L"Нажмите 'Установить' для начала."; CreateWindowW(L"STATIC", summary.c_str(), WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 80, 600, 300, hwnd, NULL, hInst, NULL); } void DrawInstallPage(HWND hwnd) { CreateWindowW(L"STATIC", L"Установка...", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 80, 600, 25, hwnd, NULL, hInst, NULL); CreateWindowExW(0, PROGRESS_CLASSW, NULL, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 50, 110, 600, 30, hwnd, (HMENU)IDC_PROGRESS, hInst, NULL); CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY, 50, 150, 600, 250, hwnd, (HMENU)IDC_LOG, hInst, NULL); } void DrawFinishPage(HWND hwnd) { CreateWindowW(L"STATIC", L"Установка завершена!\n\n" L"Claude Code успешно установлен.\n\n" L"Что дальше:\n" L"1. Установите Node.js 22: https://nodejs.org\n" L"2. Установите OmniRoute: npm install -g omniroute\n" L"3. Запустите omniroute и получите API ключ\n" L"4. Скачайте Claude Code и распакуйте\n" L"5. Запустите start-claude.bat", WS_CHILD | WS_VISIBLE | SS_LEFT, 50, 80, 600, 300, hwnd, NULL, hInst, NULL); } void ShowPage(HWND hwnd, int page) { // Удалить все дочерние окна HWND hChild = GetWindow(hwnd, GW_CHILD); while (hChild) { HWND hNext = GetWindow(hChild, GW_HWNDNEXT); int id = GetDlgCtrlID(hChild); if (id != IDC_NEXT && id != IDC_BACK && id != IDC_CANCEL) { DestroyWindow(hChild); } hChild = hNext; } // Показать нужную страницу switch (page) { case 0: DrawWelcomePage(hwnd); break; case 1: DrawInstallPathPage(hwnd); break; case 2: DrawOmniRoutePage(hwnd); break; case 3: DrawProxyPage(hwnd); break; case 4: DrawTelegramPage(hwnd); break; case 5: DrawSummaryPage(hwnd); break; case 6: DrawInstallPage(hwnd); break; case 7: DrawFinishPage(hwnd); break; } // Обновить кнопки HWND hNext = GetDlgItem(hwnd, IDC_NEXT); HWND hBack = GetDlgItem(hwnd, IDC_BACK); EnableWindow(hBack, page > 0 && page < 6); if (page == 5) { SetWindowTextW(hNext, L"Установить"); } else if (page == 7) { SetWindowTextW(hNext, L"Завершить"); } else { SetWindowTextW(hNext, L"Далее"); } ShowWindow(hNext, page != 6 ? SW_SHOW : SW_HIDE); } void PerformInstallation(HWND hwnd) { HWND hProgress = GetDlgItem(hwnd, IDC_PROGRESS); HWND hLog = GetDlgItem(hwnd, IDC_LOG); SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); auto AddLog = [hLog](const wchar_t* text) { int len = GetWindowTextLengthW(hLog); SendMessageW(hLog, EM_SETSEL, len, len); SendMessageW(hLog, EM_REPLACESEL, FALSE, (LPARAM)text); SendMessageW(hLog, EM_REPLACESEL, FALSE, (LPARAM)L"\r\n"); }; AddLog(L"Начинаем установку..."); SendMessage(hProgress, PBM_SETPOS, 10, 0); Sleep(500); AddLog(L"Создание директории..."); CreateDirectoryRecursive(installData.installPath); AddLog(L"✓ Директория создана"); SendMessage(hProgress, PBM_SETPOS, 40, 0); Sleep(500); AddLog(L"Сохранение конфигурации..."); SaveConfig(); AddLog(L"✓ Конфигурация сохранена"); SendMessage(hProgress, PBM_SETPOS, 70, 0); Sleep(500); AddLog(L"Создание скриптов..."); CreateLaunchScript(); AddLog(L"✓ Скрипты созданы"); SendMessage(hProgress, PBM_SETPOS, 100, 0); Sleep(500); AddLog(L"\nУстановка завершена!"); currentPage = 7; ShowPage(hwnd, currentPage); } void SavePageData(HWND hwnd) { char buffer[1024]; switch(currentPage) { case 1: { GetDlgItemTextA(hwnd, IDC_INSTALL_PATH, buffer, sizeof(buffer)); installData.installPath = buffer; break; } case 2: { GetDlgItemTextA(hwnd, IDC_API_KEY, buffer, sizeof(buffer)); installData.apiKey = buffer; break; } case 3: { installData.useProxy = IsDlgButtonChecked(hwnd, IDC_USE_PROXY) == BST_CHECKED; GetDlgItemTextA(hwnd, IDC_PROXY_IP, buffer, sizeof(buffer)); installData.proxyIp = buffer; GetDlgItemTextA(hwnd, IDC_PROXY_PORT, buffer, sizeof(buffer)); installData.proxyPort = buffer; GetDlgItemTextA(hwnd, IDC_PROXY_LOGIN, buffer, sizeof(buffer)); installData.proxyLogin = buffer; GetDlgItemTextA(hwnd, IDC_PROXY_PASSWORD, buffer, sizeof(buffer)); installData.proxyPassword = buffer; break; } case 4: { GetDlgItemTextA(hwnd, IDC_TELEGRAM_TOKEN, buffer, sizeof(buffer)); installData.telegramToken = buffer; break; } } } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { // Создать кнопки CreateWindowW(L"BUTTON", L"Далее", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 550, 450, 100, 30, hwnd, (HMENU)IDC_NEXT, hInst, NULL); CreateWindowW(L"BUTTON", L"Назад", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 440, 450, 100, 30, hwnd, (HMENU)IDC_BACK, hInst, NULL); CreateWindowW(L"BUTTON", L"Отмена", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 50, 450, 100, 30, hwnd, (HMENU)IDC_CANCEL, hInst, NULL); ShowPage(hwnd, 0); break; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_NEXT: { SavePageData(hwnd); if (currentPage == 5) { currentPage = 6; ShowPage(hwnd, currentPage); PerformInstallation(hwnd); } else if (currentPage == 7) { PostQuitMessage(0); } else if (currentPage < TOTAL_PAGES) { currentPage++; ShowPage(hwnd, currentPage); } break; } case IDC_BACK: { if (currentPage > 0) { currentPage--; ShowPage(hwnd, currentPage); } break; } case IDC_CANCEL: { if (MessageBoxW(hwnd, L"Отменить установку?", L"Подтверждение", MB_YESNO | MB_ICONQUESTION) == IDYES) { PostQuitMessage(0); } break; } case IDC_BROWSE: { BROWSEINFOW bi = {0}; bi.hwndOwner = hwnd; bi.lpszTitle = L"Выберите папку установки"; bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; LPITEMIDLIST pidl = SHBrowseForFolderW(&bi); if (pidl) { wchar_t path[MAX_PATH]; if (SHGetPathFromIDListW(pidl, path)) { SetDlgItemTextW(hwnd, IDC_INSTALL_PATH, path); } CoTaskMemFree(pidl); } break; } } break; } case WM_CLOSE: { if (MessageBoxW(hwnd, L"Закрыть установщик?", L"Подтверждение", MB_YESNO | MB_ICONQUESTION) == IDYES) { DestroyWindow(hwnd); } break; } case WM_DESTROY: { PostQuitMessage(0); break; } default: return DefWindowProcW(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { hInst = hInstance; // Инициализация CoInitialize(NULL); InitCommonControls(); // Инициализация данных installData.installPath = GetUserProfilePath() + "\\ClaudeCode"; installData.useProxy = false; installData.proxyPort = "8080"; // Регистрация класса окна WNDCLASSEXW wc = {0}; wc.cbSize = sizeof(WNDCLASSEXW); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = L"ClaudeInstaller"; RegisterClassExW(&wc); // Создание окна hwndMain = CreateWindowExW( 0, L"ClaudeInstaller", L"Claude Code Installer v1.0", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 750, 550, NULL, NULL, hInstance, NULL); if (!hwndMain) { return 0; } // Центрирование окна RECT rc; GetWindowRect(hwndMain, &rc); int xPos = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2; int yPos = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2; SetWindowPos(hwndMain, NULL, xPos, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE); ShowWindow(hwndMain, nCmdShow); UpdateWindow(hwndMain); // Цикл сообщений MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } CoUninitialize(); return (int)msg.wParam; }