#ifdef WIN32 // Для Windows MSVC ============================================================ #include #include #include #include #include #include // Для IsWindows7OrGreater() #pragma comment(lib, "shlwapi.lib") //============================================================================== // Проверка версии Windows (требуется Windows 7+) bool IsSupportedWindowsVersion() { return IsWindows7OrGreater(); } //============================================================================== // Проверка существования файла bool FileExists(const std::wstring& path) { DWORD attrs = GetFileAttributesW(path.c_str()); return (attrs != INVALID_FILE_ATTRIBUTES) && !(attrs & FILE_ATTRIBUTE_DIRECTORY); } //============================================================================== // Поиск всех подкаталогов, содержащих "lib" в имени (регистронезависимо) std::vector FindLibSubdirectories(const std::wstring& baseDir) { std::vector result; WIN32_FIND_DATAW findData; std::wstring searchPath = baseDir + L"\\*"; HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findData); if (hFind != INVALID_HANDLE_VALUE) { do { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { std::wstring dirName = findData.cFileName; if (dirName != L"." && dirName != L"..") { // Преобразуем в нижний регистр для проверки std::wstring lowerName = dirName; std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); if (lowerName.find(L"lib") != std::wstring::npos) { result.push_back(baseDir + L"\\" + dirName); } } } } while (FindNextFileW(hFind, &findData)); FindClose(hFind); } return result; } //============================================================================== // Получение директории текущего EXE std::wstring GetExeDirectory() { wchar_t buf[MAX_PATH]; GetModuleFileNameW(nullptr, buf, MAX_PATH); return std::wstring(buf).substr(0, std::wstring(buf).find_last_of(L"\\/")); } //============================================================================== // Построение пути к целевой программе std::wstring GetTargetPath() { // Получаем путь к текущему исполняемому файлу wchar_t currentPath[MAX_PATH]; GetModuleFileNameW(nullptr, currentPath, MAX_PATH); // Извлекаем имя файла (без пути) std::wstring exePath(currentPath); size_t lastSlash = exePath.find_last_of(L"\\/"); std::wstring exeName = (lastSlash == std::wstring::npos) ? exePath : exePath.substr(lastSlash + 1); // Формируем путь к программе в подкаталоге bin std::wstring targetPath = exePath.substr(0, lastSlash + 1) + L"bin\\" + exeName; if (!FileExists(targetPath)) { MessageBoxW(nullptr, (L"File not found:\n" + targetPath).c_str(), L"Error", MB_ICONERROR); return L""; } return targetPath; } //============================================================================== // Создание нового блока окружения с обновлённым PATH std::wstring BuildEnvironment() { std::wstring baseDir = GetExeDirectory(); std::wstring newPath; // 1. Обновляем PATH const std::vector paths = { baseDir + L"\\bin", baseDir + L"\\modules", baseDir + L"\\plugins" }; for (const auto& path : paths) { if (PathIsDirectoryW(path.c_str())) { if (!newPath.empty()) newPath += L';'; newPath += path; } } // Добавляем все подкаталоги с "lib" в имени auto libDirs = FindLibSubdirectories(baseDir); for (const auto& path : libDirs) { if (!newPath.empty()) newPath += L";"; newPath += path; } // Добавляем системный PATH wchar_t sysPath[32767]; GetEnvironmentVariableW(L"PATH", sysPath, 32767); newPath = newPath + L';' + sysPath; // 2. Обрабатываем QT_PLUGIN_PATH std::wstring qtPluginPath = baseDir + L"\\plugins"; wchar_t oldQtPluginPath[32767]; DWORD qtPathSize = GetEnvironmentVariableW(L"QT_PLUGIN_PATH", oldQtPluginPath, 32767); if (qtPathSize > 0) { // Если переменная уже существует, заменяем её значение qtPluginPath = baseDir + L"\\plugins;" + oldQtPluginPath; } // 3. Формируем полный блок среды std::wstring envBlock = L"PATH=" + newPath + L'\0' + L"QT_PLUGIN_PATH=" + qtPluginPath + L'\0'; // Копируем остальные переменные (кроме PATH и QT_PLUGIN_PATH) LPWCH envStrings = GetEnvironmentStringsW(); for (LPWSTR var = envStrings; *var; var += wcslen(var) + 1) { if (wcsncmp(var, L"PATH=", 5) != 0 && wcsncmp(var, L"QT_PLUGIN_PATH=", 15) != 0) { envBlock += std::wstring(var) + L'\0'; } } envBlock += L'\0'; FreeEnvironmentStringsW(envStrings); return envBlock; } //============================================================================== int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { // Проверка версии Windows if (!IsSupportedWindowsVersion()) { MessageBoxW(nullptr, L"Minimum version Windows 7", L"Error version", MB_ICONERROR); return 1; } // Получаем путь к целевой программе std::wstring targetPath = GetTargetPath(); if (targetPath.empty()) return 1; // Подготавливаем окружение std::wstring envBlock = BuildEnvironment(); // Запускаем процесс STARTUPINFOW si = { sizeof(si) }; PROCESS_INFORMATION pi; std::wstring cmdLine = L"\"" + targetPath + L"\""; LPWSTR args = GetCommandLineW(); if (args) { std::wstring fullArgs = args; size_t pos = fullArgs.find(L' '); if (pos != std::wstring::npos) { cmdLine += fullArgs.substr(pos); } } if (!CreateProcessW( targetPath.c_str(), &cmdLine[0], nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, (LPVOID)envBlock.c_str(), nullptr, &si, &pi )) { DWORD err = GetLastError(); MessageBoxW(nullptr, (L"Error create process (code " + std::to_wstring(err) + L")\n" + targetPath).c_str(), L"Error", MB_ICONERROR); return 1; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return 0; } //============================================================================== #else // Для Linux GCC =============================================================== //============================================================================== #endif //==============================================================================