fix: Implemented forwarder executable (#1308)
Fixes random .NET plugin crash caused by the console window being freed on the same process. ### Problem description Sometimes when launching from the explorer ImHex crashes ### Implementation description We've implemented a launcher to avoid freeing the std streams, that generated the bug. ### Screenshots N/A ### Additional things Blame windows console subsystem
This commit is contained in:
parent
1a2a926b77
commit
691df0fc83
@ -253,6 +253,9 @@ macro(createPackage)
|
|||||||
set(CPACK_GENERATOR "DragNDrop")
|
set(CPACK_GENERATOR "DragNDrop")
|
||||||
else()
|
else()
|
||||||
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
if(WIN32) # Forwarder is only needed on Windows
|
||||||
|
install(TARGETS imhex-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CREATE_PACKAGE)
|
if (CREATE_PACKAGE)
|
||||||
@ -608,11 +611,13 @@ function(generatePDBs)
|
|||||||
)
|
)
|
||||||
FetchContent_Populate(cv2pdb)
|
FetchContent_Populate(cv2pdb)
|
||||||
|
|
||||||
set(PDBS_TO_GENERATE main libimhex ${PLUGINS})
|
set(PDBS_TO_GENERATE main imhex-forwarder libimhex ${PLUGINS})
|
||||||
add_custom_target(pdbs)
|
add_custom_target(pdbs)
|
||||||
foreach (PDB ${PDBS_TO_GENERATE})
|
foreach (PDB ${PDBS_TO_GENERATE})
|
||||||
if (PDB STREQUAL "main")
|
if (PDB STREQUAL "main")
|
||||||
set(GENERATED_PDB imhex)
|
set(GENERATED_PDB imhex)
|
||||||
|
elseif (PDB STREQUAL "imhex-forwarder")
|
||||||
|
set(GENERATED_PDB imhex-gui)
|
||||||
elseif (PDB STREQUAL "libimhex")
|
elseif (PDB STREQUAL "libimhex")
|
||||||
set(GENERATED_PDB libimhex)
|
set(GENERATED_PDB libimhex)
|
||||||
else ()
|
else ()
|
||||||
|
@ -28,11 +28,28 @@ set(LIBROMFS_PROJECT_NAME imhex)
|
|||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/main/libromfs EXCLUDE_FROM_ALL)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/main/libromfs EXCLUDE_FROM_ALL)
|
||||||
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
set_target_properties(main PROPERTIES
|
if (WIN32)
|
||||||
|
# HACK: `imhex` -> `imhex-gui` and we add a forwarder as `imhex`, so that the user can just run `imhex` and it will start the GUI
|
||||||
|
# Workaround for .NET plugin crashing caused by the console window being freed.
|
||||||
|
set(IMHEX_APPLICATION_NAME "imhex-gui")
|
||||||
|
add_executable(imhex-forwarder
|
||||||
|
source/forwarder/main.cpp
|
||||||
|
${IMHEX_ICON})
|
||||||
|
target_link_libraries(imhex-forwarder PRIVATE libwolv-io ${FMT_LIBRARIES})
|
||||||
|
set_target_properties(imhex-forwarder PROPERTIES
|
||||||
OUTPUT_NAME "imhex"
|
OUTPUT_NAME "imhex"
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||||
CXX_VISIBILITY_PRESET hidden
|
CXX_VISIBILITY_PRESET hidden
|
||||||
POSITION_INDEPENDENT_CODE ON)
|
POSITION_INDEPENDENT_CODE ON)
|
||||||
|
else ()
|
||||||
|
set(IMHEX_APPLICATION_NAME "imhex")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set_target_properties(main PROPERTIES
|
||||||
|
OUTPUT_NAME ${IMHEX_APPLICATION_NAME}
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||||
|
CXX_VISIBILITY_PRESET hidden
|
||||||
|
POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
|
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
|
||||||
|
|
||||||
|
54
main/source/forwarder/main.cpp
Normal file
54
main/source/forwarder/main.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <wolv/io/fs.hpp>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
HWND consoleWindow = ::GetConsoleWindow();
|
||||||
|
DWORD processId = 0;
|
||||||
|
::GetWindowThreadProcessId(consoleWindow, &processId);
|
||||||
|
if (GetCurrentProcessId() == processId) {
|
||||||
|
FreeConsole();
|
||||||
|
} else {
|
||||||
|
auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (hConsole != INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD mode = 0;
|
||||||
|
if (::GetConsoleMode(hConsole, &mode) == TRUE) {
|
||||||
|
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT;
|
||||||
|
::SetConsoleMode(hConsole, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto executablePath = wolv::io::fs::getExecutablePath();
|
||||||
|
auto executableFullPath = executablePath->parent_path() / "imhex-gui.exe";
|
||||||
|
|
||||||
|
PROCESS_INFORMATION process;
|
||||||
|
STARTUPINFOW startupInfo;
|
||||||
|
ZeroMemory(&process, sizeof(PROCESS_INFORMATION));
|
||||||
|
ZeroMemory(&startupInfo, sizeof(STARTUPINFOW));
|
||||||
|
startupInfo.cb = sizeof(STARTUPINFOW);
|
||||||
|
|
||||||
|
if (CreateProcessW(executableFullPath.wstring().c_str(), GetCommandLineW(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &process) == FALSE) {
|
||||||
|
auto error = GetLastError();
|
||||||
|
|
||||||
|
wchar_t errorMessageString[1024];
|
||||||
|
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, 0, errorMessageString, 1024, nullptr);
|
||||||
|
|
||||||
|
std::wstring errorMessage = L"Failed to start ImHex:\n\nError code: ";
|
||||||
|
|
||||||
|
// Format error code to have 8 digits hex
|
||||||
|
wchar_t errorCodeString[11];
|
||||||
|
swprintf_s(errorCodeString, 11, L"0x%08X", error);
|
||||||
|
|
||||||
|
errorMessage += errorCodeString;
|
||||||
|
errorMessage += L"\n\n";
|
||||||
|
errorMessage += errorMessageString;
|
||||||
|
|
||||||
|
MessageBoxW(nullptr, errorMessage.c_str(), L"ImHex Forwarder", MB_OK | MB_ICONERROR);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSingleObject(process.hProcess, INFINITE);
|
||||||
|
CloseHandle(process.hProcess);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -237,7 +237,6 @@ namespace hex {
|
|||||||
::GetWindowThreadProcessId(consoleWindow, &processId);
|
::GetWindowThreadProcessId(consoleWindow, &processId);
|
||||||
if (GetCurrentProcessId() == processId) {
|
if (GetCurrentProcessId() == processId) {
|
||||||
ShowWindow(consoleWindow, SW_HIDE);
|
ShowWindow(consoleWindow, SW_HIDE);
|
||||||
FreeConsole();
|
|
||||||
log::impl::redirectToFile();
|
log::impl::redirectToFile();
|
||||||
} else {
|
} else {
|
||||||
auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
|
auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user