fix(windows console): properly bind windows console
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
9137721e8e
commit
5740ee0444
@ -135,13 +135,16 @@
|
|||||||
#include "updater/MacSparkleUpdater.h"
|
#include "updater/MacSparkleUpdater.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
#include <windows.h>
|
#include <fcntl.h>
|
||||||
|
#include <io.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define STRINGIFY(x) #x
|
#define STRINGIFY(x) #x
|
||||||
@ -168,33 +171,116 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
|
||||||
|
// taken from https://stackoverflow.com/a/25927081
|
||||||
|
// getting a proper output to console with redirection support on windows is apearently hell
|
||||||
|
void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
|
||||||
|
{
|
||||||
|
// Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been
|
||||||
|
// observed that the file number of our standard handle file objects can be assigned internally to a value of -2
|
||||||
|
// when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our
|
||||||
|
// call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value
|
||||||
|
// before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to
|
||||||
|
// use the "nul" device, which will place them into a valid state, after which we can redirect them to our target
|
||||||
|
// using the "_dup2" function.
|
||||||
|
if (bindStdIn) {
|
||||||
|
FILE* dummyFile;
|
||||||
|
freopen_s(&dummyFile, "nul", "r", stdin);
|
||||||
|
}
|
||||||
|
if (bindStdOut) {
|
||||||
|
FILE* dummyFile;
|
||||||
|
freopen_s(&dummyFile, "nul", "w", stdout);
|
||||||
|
}
|
||||||
|
if (bindStdErr) {
|
||||||
|
FILE* dummyFile;
|
||||||
|
freopen_s(&dummyFile, "nul", "w", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect unbuffered stdin from the current standard input handle
|
||||||
|
if (bindStdIn) {
|
||||||
|
HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
if (stdHandle != INVALID_HANDLE_VALUE) {
|
||||||
|
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
|
||||||
|
if (fileDescriptor != -1) {
|
||||||
|
FILE* file = _fdopen(fileDescriptor, "r");
|
||||||
|
if (file != NULL) {
|
||||||
|
int dup2Result = _dup2(_fileno(file), _fileno(stdin));
|
||||||
|
if (dup2Result == 0) {
|
||||||
|
setvbuf(stdin, NULL, _IONBF, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect unbuffered stdout to the current standard output handle
|
||||||
|
if (bindStdOut) {
|
||||||
|
HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (stdHandle != INVALID_HANDLE_VALUE) {
|
||||||
|
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
|
||||||
|
if (fileDescriptor != -1) {
|
||||||
|
FILE* file = _fdopen(fileDescriptor, "w");
|
||||||
|
if (file != NULL) {
|
||||||
|
int dup2Result = _dup2(_fileno(file), _fileno(stdout));
|
||||||
|
if (dup2Result == 0) {
|
||||||
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect unbuffered stderr to the current standard error handle
|
||||||
|
if (bindStdErr) {
|
||||||
|
HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
if (stdHandle != INVALID_HANDLE_VALUE) {
|
||||||
|
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
|
||||||
|
if (fileDescriptor != -1) {
|
||||||
|
FILE* file = _fdopen(fileDescriptor, "w");
|
||||||
|
if (file != NULL) {
|
||||||
|
int dup2Result = _dup2(_fileno(file), _fileno(stderr));
|
||||||
|
if (dup2Result == 0) {
|
||||||
|
setvbuf(stderr, NULL, _IONBF, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the
|
||||||
|
// standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In
|
||||||
|
// versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything
|
||||||
|
// has been read from or written to the targets or not.
|
||||||
|
if (bindStdIn) {
|
||||||
|
std::wcin.clear();
|
||||||
|
std::cin.clear();
|
||||||
|
}
|
||||||
|
if (bindStdOut) {
|
||||||
|
std::wcout.clear();
|
||||||
|
std::cout.clear();
|
||||||
|
}
|
||||||
|
if (bindStdErr) {
|
||||||
|
std::wcerr.clear();
|
||||||
|
std::cerr.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||||
{
|
{
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
// attach the parent console
|
// attach the parent console if stdout not already captured
|
||||||
if(AttachConsole(ATTACH_PARENT_PROCESS))
|
auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||||
{
|
if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) {
|
||||||
// if attach succeeds, reopen and sync all the i/o
|
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
if(freopen("CON", "w", stdout))
|
BindCrtHandlesToStdHandles(true, true, true);
|
||||||
{
|
|
||||||
std::cout.sync_with_stdio();
|
|
||||||
}
|
|
||||||
if(freopen("CON", "w", stderr))
|
|
||||||
{
|
|
||||||
std::cerr.sync_with_stdio();
|
|
||||||
}
|
|
||||||
if(freopen("CON", "r", stdin))
|
|
||||||
{
|
|
||||||
std::cin.sync_with_stdio();
|
|
||||||
}
|
|
||||||
auto out = GetStdHandle (STD_OUTPUT_HANDLE);
|
|
||||||
DWORD written;
|
|
||||||
const char * endline = "\n";
|
|
||||||
WriteConsole(out, endline, strlen(endline), &written, NULL);
|
|
||||||
consoleAttached = true;
|
consoleAttached = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
||||||
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
||||||
|
Loading…
Reference in New Issue
Block a user