Make interactive console/window interaction in gui application - c++

What i want:
An application, where there are a gui window and console window. Window can be clicked on, dragged, etcetera. At any given moment, console can be chosen, and a line entered, that will be processed.
What i already have:
An application, that allocates and attaches console to itself, then redirects standard streams to it. Code is:
AllocConsole() ;
AttachConsole( GetCurrentProcessId());
freopen("CONIN$","rb",stdin); // reopen stdin handle as console window input
freopen("CONOUT$","wb",stdout); // reopen stout handle as console window output
freopen("CONOUT$","wb",stderr); // reopen stderr handle as console window output
Then registers window class, creates and shows a window. Output into console works fine, interaction with window is correct.
However, i cannot input anything into console. I can make a guess about it: if i call something like std::cin >> my_string, i will be able to enter a line - but interaction with a window will stop until the input is completed. Is that correct? How can i make application behave in a way i described above?
update:
I have found related question: Test if stdin has input for C++ (windows and/or linux)
The code for determining, whether there are characters in console input was given there as follows:
bool StdinOpen() {
static HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD bytes_left;
PeekNamedPipe(handle, NULL, 0, NULL, &bytes_left, NULL);
return bytes_left;
}
However, it returns some exorbitant numbers, as if there always is input in console.

I'd start by initializing the bytes_left variable and check the return value.
bool StdinOpen() {
static HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD bytes_left = 0;
if (!PeekNamedPipe(handle, NULL, 0, NULL, &bytes_left, NULL))
return false;
return bytes_left != 0;
}

Related

Start chromium browser in minimized state (Win32/WinAPI)

I want to start browser in minimized state, however in this list there's no option for minimizing. So I thought of using ShowWindow() but some issues arise. I don't know how to use EnumWindows() or its derivatives. Only alternative I know is GetWindow() but I'm not sure of the position of window at Z-order. This is my solution:
HWND hwnd,hwnd2; //hwnd is my application's top level window
char t[128];
std::string t2;
for(int i=0; i<128&&t2!="found"; i++)
{
if(!i||i==64) hwnd2=hwnd; //turn direction
hwnd2=GetWindow(hwnd2,i<64?2:3); //loop backwards and forwards
GetWindowText(hwnd2,t,GetWindowTextLength(hwnd2)+1);
t2=t; if(t2.find("New")!=-1) t2="Found"; //Default title is "New Tab..."
}
ShowWindow(hwnd2,SW_MINIMIZE);
Assuming there won't be more than 128 windows, it works fine but since a window takes ~2 seconds to open, at the time ShowWindow() occurs, the window is not yet ready. So I used a timer for it.
SetTimer(hwnd,1,2000,0);
and
case WM_TIMER:
KillTimer(hwnd,1);
ShowWindow(hwnd2,SW_MINIMIZE);
break;
But it's impossible to know the exact time so the window gets minimized after it's shown for some milliseconds. I tried setting multiple timers in an interval of 50ms.
for(int i=0; i<50; i++) SetTimer(hwnd,1+i,i*50,0);
and
case WM_TIMER:
KillTimer(hwnd,wParam);
ShowWindow(hwnd2,SW_MINIMIZE);
break;
It usually minimizes window before it's shown, not always though. Also it changes the cursor to busy state every 50ms. Is there a way to stop this when the minimizing successfully performed once? It's not possible to determine this from the return value of ShowWindow() so is there a way? How can minimizing window before it's shown be guaranteed? Can I somehow make it wait till browser window is ready then sending ShowWindow() on the right time at once? How can I improve my solution into an easier one?
WinExec gives you very little control over spawned process.
Use CreateProcess, and set LPSTARTUPINFOA lpStartupInfo's WORD wShowWindow; to SW_MINIMIZE
Make sure that dwFlags contains STARTF_USESHOWWINDOW
Here is how to use it:
#include <windows.h>
int main()
{
PROCESS_INFORMATION processInformation = { 0 };
STARTUPINFO startupInfo = { sizeof STARTUPINFO };
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_MINIMIZE;
wchar_t cmd[] = L"C:\\Program Files\\Internet Explorer\\iexplore.exe";
// Create the process
BOOL result = CreateProcess(NULL,
cmd, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
FALSE, // handles are not inherited
NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&startupInfo, // STARTUPINFO pointer
&processInformation); // receives PROCESS_INFORMATION
}
UPDATE
In the referenced doc, they state:
the wShowWindow member is used if the nCmdShow parameter of ShowWindow is set to SW_SHOWDEFAULT.
There is similar comment on the position and size field.
Apparently, some application do NOT use the defaults. For example, chrome and calc open their window at the position it was closed previously.
You can find that stored location in the Registry and update it.
More info
Google Chrome default opening position and size suggests to edit Preferences file. It looks like this:
"window_placement":{"bottom":1363,"left":406,"maximized":false,"right":1356,"top":217,"visible":false,"work_area_bottom":1400,"work_area_left":0,"work_area_right":2560,"work_area_top":0}
I've tried to invent keys like minimized, hidden, visible - no luck :)
You could shift the window off-screen; I have partial success - chrome moves it back in so at least a few pixels show...

Redirecting child process stdout via console screen buffer in Windows 10 C++

I am trying to redirect the stdout of a child process in Windows. Both are console programs. I don't have the source code of the child process, so I can't force it to flush the buffer. As discussed here and here, for the implementation of printf and similar, the C runtime buffers everything except consoles and printers. So the solution is apparently to create a console screen buffer using, appropriately enough, CreateConsoleScreenBuffer. I'm using the approach from codeproject.
PROCESS_INFORMATION pi;
HANDLE hConsole;
const COORD origin = { 0, 0 };
// Default security descriptor. Set inheritable.
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE; // So the child can use it
// Create and initialize screen buffer
hConsole = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE, // Desired access
FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode to child processes
&sa, // SECURITY_ATTRIBUTES
CONSOLE_TEXTMODE_BUFFER, // Must be this.
NULL // Reserved. Must be NULL
);
DWORD dwDummy;
FillConsoleOutputCharacter(hConsole, '\0', MAXLONG, origin, &dwDummy)
Now I direct the child's stdout to the console and start the process
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_FORCEOFFFEEDBACK | STARTF_USESTDHANDLES; // first one prevents cursor from showing loading.
si.hStdOutput = hConsole;
//...
// Get the command line and environmental block
//...
if (! CreateProcess(
NULL, // module name.
(char*)command_line.c_str(), // command line
NULL, // process SECURITY_ATTRIBUTES
NULL, // thread SECURITY_ATTRIBUTES
TRUE, // inherit handles
NULL, // creation flags
enviros, // environmentBlock (enviros=NULL for testing)
cDir, // working directory
&si, // STARTUP_INFO object
&pi // PROCESSINFO
) ){
auto test = GetLastError();
CloseHandle(hConsole);
return false;
}
CloseHandle(pi.hThread);
Then, in a loop, I can use ReadConsoleOutputCharacter to grab output, as shown at the codeproject link. It looks like
//... some initialization
GetConsoleScreenBufferInfo(hConsole, &csbi);
DWORD count = (csbi.dwCursorPosition.Y - lastpos.Y)*lineWidth + csbi.dwCursorPosition.X - lastpos.X;
LPTSTR buffer = (LPTSTR)LocalAlloc(0, count * sizeof(TCHAR));
ReadConsoleOutputCharacter(hConsole, buffer, count, lastpos, &count);
DWORD dwDummy;
FillConsoleOutputCharacter(hConsole, '\0', count, lastpos, &dwDummy);
//... Now move the cursor and grab the data from `buffer`
On Windows 7/8.1 this works fine for all programs. On Windows 10, some programs seem to be bypassing the supplied handles and printing directly to the parent console, preventing me from grabbing the output as I need.
I do have an additional clue. If I force the process to create a new console window, i.e.
CreateProcess(NULL, (char*)command_line.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, enviros, cDir, &si, &pi)
but still redirect the handles in the STARTUPINFO object, the new console will display a single line that says The system cannot write to the specified device, which just happens to be the exact wording of Windows error code ERROR_WRITE_FAULT = 29 in the MSDN docs. This happens only for those programs which aren't working as expected. Other programs, the new console is blank and they still function as expected.
My first thought is a permissions problem, but I have wide open permissions on the directories of the relevant executables.
Things I've tried
A different computer with Windows 10
Different versions of MS Visual C++ runtime
Setting the working directory explicitly in CreateProcess
Adding a super-permissive DACL to a SECURITY_ATTRIBUTES object passed to CreateProcess
Adding a super-permissive DACL to a SECURITY_ATTRIBUTES object passed to CreateConsoleScreenBuffer
Moving everything to a newly created directory under my Windows user directory
Running as administrator
Deeper
Thank you #PaulSanders for your suggestion.
To aid with anyone who might want to assist, I've made available a modified version of the RTConsole code from the codeproject page. It should compile in Visual Studio with just a retarget, I think. Around line 135, I've prepended a little string to the front of the output which takes the expected path. I've provided a pre-compiled version in there for convenience, as well.
One example of software that doesn't work is EWBF miner. For a quick test using the code I provided above, you could run
RTConsole2.exe "path\to\ewbf.exe" --help
You'll see that the prepended flag is not present in the output.
On the other hand, with ccminer, you'll get the expected behavior when running
RTConsole2.exe "path\to\ccminer.exe" --help
The new console implementation in Windows 10 has a bug in which high-level WriteConsole and WriteFile to a non-active screen buffer instead always writes to the active screen buffer. Low-level WriteConsoleOutput[Character] works correctly. Using the legacy console also works. You can enable the legacy console in the properties dialog.
Note that a process cannot use an inherited handle for a screen buffer in the parent's console if it allocates a new console due to the CREATE_NEW_CONSOLE flag. Trying to write to the screen-buffer file will fail because it's not bound to the caller's attached console (i.e. instance of conhost.exe).
Console files that are bound include "CON", "CONIN$", "CONOUT$", and a new screen buffer from CreateConsoleScreenBuffer. There are also unbound input and output console files, which are set as the standard handles when allocating a new console (e.g. via AllocConsole()). These handles access the input buffer and active screen buffer of any attached console [*]. Note that a process can have handles for console files that are bound to multiple consoles and can switch between consoles using AttachConsole.
Note also that some programs open "CONOUT$" instead of writing to the StandardOutput and StandardError handles, especially if they require a console instead of whatever the standard handles might be (e.g. a pipe or disk file). In this case it is not enough to set hStdOutput in STARTUPINFO. You have to temporarily make the new screen buffer active via SetConsoleActiveScreenBuffer. This does not affect the caller's standard handles. It sets the active screen buffer in the attached console, which is what "CONOUT$" opens. The previous screen buffer can be restored after the child process exits, or after you know the child has already opened and written to the new screen buffer.
[*] In Windows 8+, these console files are implemented by the condrv.sys device driver and opened on "\Device\ConDrv". They are respectively named "Console", "CurrentIn", "CurrentOut", "ScreenBuffer", "Input", and "Output". The filename for the console connection itself is "Connect". Internally the latter is opened as the process ConsoleHandle, which is used implicitly by the console API in some cases (e.g. GetConsoleWindow, GetConsoleCP, and GetConsoleTitle).

Highlighting text in console makes window unresponsive [duplicate]

This question already has answers here:
How and why does QuickEdit mode in Command Prompt freeze applications?
(2 answers)
Closed 6 years ago.
for an application of mine I have been playing around with the Windows API a bit, namely creating a very small wrapper for window functionality. Since I like to have console output as well, I created a console via AllocConsole(). I then noticed that highlighting text in this console (like if you want to copy something) 'freezes' the open window, ie. no messages will be processed, it is not click- or closable. Message loop and wndProc are both standard.
Two questions: is that intended/documented behaviour (I couldn't find anything about it) and if yes, is there a way to disable it? It's kind of annoying.
Thanks in advance
EDIT: as requested, the console creation code:
FILE *conOut = NULL;
FILE *conIn = NULL;
if (::AllocConsole())
{
::freopen_s(&conIn, "CONOUT$", "r", stdin);
::freopen_s(&conOut, "CONOUT$", "w", stdout);
// ...
if (conOut != NULL)
::fclose(conOut);
if (conIn != NULL)
::fclose(conIn);
::FreeConsole();
}
I created a test Win32 application with a basic Win32 project. I added a simple class to handle the console creation and tested two scenarios. What I found was the console window output will stop as if the thread generating the output is suspended when an Edit->Mark is done until the Mark is completed with a Copy or canceled.
The two scenarios tested with the Win32 application were: (1) printing to console window in a separate thread and (2) printing to console window in the main window message handling logic.
The particulars of the test program and details of the two scenarios tested are as follows.
Console.h
#pragma once
#include <stdio.h>
class CConsole
{
public:
CConsole(void);
~CConsole(void);
int Create(void);
public:
FILE *m_conOut;
FILE *m_conIn;
};
Console.cpp
#include "StdAfx.h"
#include "Console.h"
CConsole::CConsole(void)
{
}
CConsole::~CConsole(void)
{
}
int CConsole::Create(void)
{
if (::AllocConsole())
{
::freopen_s(&m_conIn, "CONIN$", "r", stdin);
::freopen_s(&m_conOut, "CONOUT$", "w", stdout);
}
return 0;
}
In the main file at the near the top where the Win32 project wizard put some global variables, I added an additional global variable CConsole myConsole; for my console and then I added a bit further down a simple function that is the target of a _beginthreadex(). The function looks like:
unsigned __stdcall myThread( void *x )
{
HWND hWnd = (HWND)x;
// allow for two different test scenarios depending on whether the
// SendMessage() is commented out or the fprintf() is commented out.
// if SendMessage() is live then the main window will write to the console window
// if fprintf() is live then this thread will write to the console window.
for (int i = 0; i < 50; i++) {
// SendMessage (hWnd, WM_USER, i, 0); // send a message to main window to request print
fprintf (myConsole.m_conOut, "This is line %d\n", i); // print from this thread
Sleep (1000);
}
return 0;
}
In the InitInstance(HINSTANCE hInstance, int nCmdShow) just before the return statement, I added the following two lines of code:
myConsole.Create();
_beginthreadex (NULL, 0, myThread, hWnd, 0, NULL);
Finally in the main message loop that handles the messages for the main window I added an additional message target:
case WM_USER:
fprintf (myConsole.m_conOut, "This is line %d\n", wParam);
break;
I then tried two different experiments by commenting out one of the two lines in my function that is the target of the _beginthreadex().
One was to print to the console window using fprintf() within that thread. The second test case was to send a message of WM_USER to the main window and ask it to use fprintf() to print to the console window.
What I found was that with the printing being done by the thread then I observed the following behavior when I used the Edit->Mark to begin the procedure of marking text to copy:
the main window was responsive to menu choices
the console window output stopped
when I cleared the mark or copied text, console window output resumed
The behavior was as if the thread writing to the console window was suspended until the Mark and Copy procedure was completed.
When the printing was done by the main window's message loop when handling the WM_USER message then I observed the following behavior when I used the Edit->Mark to begin the procedure of marking text to copy:
the main window was unresponsive to menu choices
the console window output stopped
when I cleared the mark or copied text, main window responsiveness returned as did console output
For some additional information about the Console Window Subsystem see Consoles. For a bit of information about the technology see WinEventProc Callback Function along with SetWinEventHook which describes this functionality to some extent as well as What Are WinEvents? and In-Context Hook Function Precautions.
See also Console Window Host in the book Windows Internals for a brief overview of the Console Window Subsystem.
And see Windows 7 / Windows Server 2008 R2: Console Host for an introduction to the architecture changes.
Finally The Console Host Process in Windows 7 from the book Inside Windows Debugging shows how to "discover the various layers involved in the printf sequence".
It may be possible to use the Console functions at a lower level to directly interface with the Console Window Subsystem in order to prevent the freezing of the thread which is doing I/O to the console window.

Getting the messages back to the same command line from where the MFC application was launched

I am executing an MFC Application from command line which takes four command line arguments.One of the argument is the directory path.
If the path is wrong then I want to show a Message "Bad Path" on the same command line
Note : For showing I don't want to take a new command line .
Basically that's not supported. There is sort of known "workaround" for that, using AttachConsole(-1) to attach parent process console. Has disadvantages of course (like, parent console will not wait for your EXE to terminate, because it's not a "console" app). Anyways, basic idea:
void WriteToParentConsole()
{
if (AttachConsole(-1))
{
char msg[] = "Bad Path!";
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, sizeof(msg), NULL, NULL);
// send ENTER (optional)
// ::SendMessage(GetConsoleWindow(), WM_CHAR, VK_RETURN, 0);
FreeConsole();
}
}
You can check out this article for example, or just google something on AttachConsole/GUI vs Console for more information:
http://www.tillett.info/2013/05/13/how-to-create-a-windows-program-that-works-as-both-as-a-gui-and-console-application/

How can I detect if there is input waiting on stdin on windows?

I want to detect whether or not there is input waiting on stdin in Windows.
I use the following generic structure on Linux:
fd_set currentSocketSet;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int result = 1;
while (result > 0){
FD_ZERO(&currentSocketSet);
FD_SET(STDIN, &currentSocketSet);
result = select(STDIN+1, &currentSocketSet, NULL, NULL, &tv);
if (result == -1){
printf("Network Error -- select errored with id=%d.\n", errno);
return;
} else if (result > 0){
//...do stuff
}
}
Note: I do not want to deal with the keyboard and keyboard functions like kbhit. I want a way to do what I asked. I do not want a third party library to do this either, I would like a native Windows library call to get the answer.
Note #2: On windows the above code fails with windows error code 10038 "An operation was attempted on something that is not a socket" which probably means that windows does not support selecting on STDIN.
As stated in the ReadConsoleInput() documentation:
A process can specify a console input buffer handle in one of the wait functions to determine when there is unread console input. When the input buffer is not empty, the state of a console input buffer handle is signaled.
To determine the number of unread input records in a console's input buffer, use the GetNumberOfConsoleInputEvents function. To read input records from a console input buffer without affecting the number of unread records, use the PeekConsoleInput function. To discard all unread records in a console's input buffer, use the FlushConsoleInputBuffer function.
You can use GetStdHandle() to get a handle to STDIN for use in the above functions.
As already pointed out, in Windows you have to use GetStdHandle() and the returned handle cannot be mixed with sockets. But luckily, the returned handle can be tested with WaitForSingleObject(), just like many other handles in Windows. Therefere, you could do something like this:
#include <stdio.h>
#include <windows.h>
BOOL key_was_pressed(void)
{
return (WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE),0)==WAIT_OBJECT_0);
}
void wait_for_key_press(void)
{
WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE),INFINITE);
}
int main()
{
if(key_was_pressed())
printf("Someone pressed a key beforehand\n");
printf("Wait until a key is pressed\n");
wait_for_key_press();
if(key_was_pressed())
printf("Someone pressed a key\n");
else
printf("That can't be happening to me\n");
return 0;
}
EDIT: Forgot to say that you need to read the characters from the handle in order to key_was_pressed() to return FALSE.
As you know, Linux != Windows, and you're not going to get the same semantics for a "select()" in both environments.
You didn't specify whether this is a Windows GUI or console-mode program, either. It makes a difference.
... HOWEVER ...
Two Win32 APIs you might want to look at:
GetAsyncKeyState
PeekConsoleInput
'Hope that helps
PS:
If this is a console-mode program, you're going to need a window handle. Call GetStdHandle(STD_INPUT_HANDLE) to get it.