Initial commit
parent
2bb7478a76
commit
8b41090149
|
@ -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
|
||||
|
|
@ -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.
|
|
@ -0,0 +1,25 @@
|
|||
MIT лицензия
|
||||
|
||||
Copyright (c) 2024 Evgeny Teterin (nayk) <nayk@nxt.ru>
|
||||
|
||||
Данная лицензия разрешает лицам, получившим копию
|
||||
данного программного обеспечения и сопутствующей документации
|
||||
(в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно
|
||||
использовать Программное Обеспечение без ограничений,
|
||||
включая неограниченное право на использование, копирование, изменение,
|
||||
слияние, публикацию, распространение, сублицензирование и/или продажу
|
||||
копий Программного Обеспечения, а также лицам, которым предоставляется
|
||||
данное Программное Обеспечение, при соблюдении следующих условий:
|
||||
|
||||
Указанное выше уведомление об авторском праве и данные условия
|
||||
должны быть включены во все копии или значимые части данного Программного Обеспечения.
|
||||
|
||||
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ»,
|
||||
БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ,
|
||||
ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ
|
||||
НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ.
|
||||
НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ
|
||||
ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ,
|
||||
ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ,
|
||||
ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
|
||||
ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
|
|
@ -1,2 +1,3 @@
|
|||
# Launcher
|
||||
# Application Launcher
|
||||
|
||||
Запускатор для приложений Qt и др.
|
||||
|
|
|
@ -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}
|
||||
)
|
|
@ -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;
|
||||
}
|
||||
//==============================================================================
|
||||
|
Loading…
Reference in New Issue