Initial commit

main
Евгений Тетерин 2025-04-05 12:02:06 +03:00
parent 2bb7478a76
commit 8b41090149
6 changed files with 379 additions and 1 deletions

107
.gitignore vendored 100644
View File

@ -0,0 +1,107 @@
.build/
_other/
_distrib*/
# Tmp files
*~
Thumbs.db*
# C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.so.*
*.dll
*.dylib
*.ko
*.obj
*.elf
*.lib
# Qt-es
object_script.*.Release
object_script.*.Debug
*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
*.qm
*.prl
# Qt unit tests
target_wrapper.*
# QtCreator
*.autosave
# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCreator CMake
CMakeLists.txt.user*
# QtCreator 4.8< compilation database
compile_commands.json
# QtCreator local machine specific files for imported projects
*creator.user*
*_qmlcache.qrc
# ---> C
# Prerequisites
*.d
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# Fortran module files
*.mod
*.smod

9
LICENSE 100644
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2024 Evgeny Teterin (nayk) <nayk@nxt.ru>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

25
LICENSE.ru 100644
View File

@ -0,0 +1,25 @@
MIT лицензия
Copyright (c) 2024 Evgeny Teterin (nayk) <nayk@nxt.ru>
Данная лицензия разрешает лицам, получившим копию
данного программного обеспечения и сопутствующей документации
(в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно
использовать Программное Обеспечение без ограничений,
включая неограниченное право на использование, копирование, изменение,
слияние, публикацию, распространение, сублицензирование и/или продажу
копий Программного Обеспечения, а также лицам, которым предоставляется
данное Программное Обеспечение, при соблюдении следующих условий:
Указанное выше уведомление об авторском праве и данные условия
должны быть включены во все копии или значимые части данного Программного Обеспечения.
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ»,
БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ,
ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ
НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ.
НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ
ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ,
ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ,
ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.

View File

@ -1,2 +1,3 @@
# Launcher
# Application Launcher
Запускатор для приложений Qt и др.

View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.24)
project(launcher LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Настройки для MSVC
if(MSVC)
# Статическая линковка CRT
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Оптимизация размера и скорости
add_compile_options(
"$<$<CONFIG:RELEASE>:/Os>" # Оптимизация по размеру
"$<$<CONFIG:RELEASE>:/Oy>" # Отключение кадров стека
"$<$<CONFIG:RELEASE>:/GL>" # Включение LTO
)
# Настройки линковщика
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG /OPT:REF /OPT:ICF")
endif()
add_executable(${PROJECT_NAME} WIN32 main.cpp)
target_link_libraries(${PROJECT_NAME}
PRIVATE Kernel32.lib
PRIVATE shlwapi.lib
)
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

201
sources/main.cpp 100644
View File

@ -0,0 +1,201 @@
#include <windows.h>
#include <string>
#include <vector>
#include <shlwapi.h>
#include <algorithm>
#include <versionhelpers.h> // Для 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<std::wstring> FindLibSubdirectories(const std::wstring& baseDir)
{
std::vector<std::wstring> 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<std::wstring> 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;
}
//==============================================================================