Holding scroll-bar gets command prompt to pause in Windows - c++

I have a program where I record data through an ADC system from National Instruments (NI).
The device buffers information for some time, and then the program collects the buffer data at some point. If the program collects data larger than the buffer, then the buffer would have to free without my program receiving the data, which will cause the NI library to throw an exception saying that requested data isn't available anymore, since it was lost.
Since my program is a command-prompt program, if the user clicks and holds the scrollbar, the program pauses, which could get this problem to happen.
How can I get over this problem without increasing the buffer size? Can I disable this holding thing in Windows?
Thanks.

Only the thread that is attempting to output to the console is blocked. Make this a separate thread, and your problem goes away.
Of course, you'll need to buffer up your output, and do something sensible if the buffer overflows.
For reference, here's the simple code I used to test this, you will note that the counter continues to increase even when the scroll bar is held down:
#include <Windows.h>
#include <stdio.h>
volatile int n = 0;
DWORD WINAPI my_thread(LPVOID parameter)
{
for (;;)
{
n = n + 1;
Sleep(800);
}
}
int main(int argc, char ** argv)
{
if (!CreateThread(NULL, 0, my_thread, NULL, 0, NULL))
{
printf("Error %u from CreateThread\n", GetLastError());
return 0;
}
for (;;)
{
printf("Hello! We're at %u\n", n);
Sleep(1000);
}
return 0;
}

Whilst there may be ways to bypass each individual problem you can possibly conceive with the output [including for example running it over a network on a sometimes slow output link, or some such], I think the correct thing to do is to disconnect your output from your collecting of data. It shouldn't be hard to do this by adding a separate thread that collects the data, and having the main thread display to the command prompt window. That way, not matter which variation of "output is blocked" Windows throws at you, it will work - at least until you run out of RAM, but tat that point it's YOUR program's decision to do something [e.g. throw away some data or some such].
This is generally how the problem "I need to collect something, and I also need to allow users to view the data, but I don't want the two to interfere with each other" is solved.

First use the GetConsoleWindow winapi function and get the HWND of your console.
now i suggest two ways to do this,
Method I
Subclass the window by creating your own WindowProcedure. (get help from here)
Now that you have subclassed it, you can intercept the WM_VSCROLL and WM_HSCROLL messages and do your own remedy to your code.
Method II
Change the size of the window using some function like SetWindowPos so that the scroll bars are not needed.
or Change the size of the console screen buffer so that the scroll bars are not needed.
Method I has lot of control over the application, but its a little bit complex than the method II which is very simple.
If you want to forbid the user from resizing the console window, just remove the WS_THICKFRAME from the WindowStyle of the console window.

I was in a similar situation and found that this kind of blocking behaviour could be caused by the quick edit "feature" of the command prompt. This question explains about it and the answer shows how to disable it. Hope that helps, even after some years :)

Related

How to stop a thread reading stdin in a C++ Linux console application?

I am writing a console application that accepts input (one-line commands) from stdin. This application reads input in a dedicated thread, all input is stored in a queue and later processed by the main thread in a safe way. When the exit command is entered by the user, it is intercepted by the input thread which stops listening for new input, the thread is joined into the main one, and the application stops as requested.
Now I am containerizing this application, but I still want to be able to attach to the container and input commands from stdin, so I specified tty and stdin_open to be true in my docker compose service file, and that did the trick.
But I also want docker compose to be able to gracefully stop the application, so I decided to implement sigTerm() in my application so that it can receive the signal from docker compose and gracefully stop, however I'm stuck on that part, because the input thread is blocking while waiting for input on stdin. I can properly receive the signal, that's not at all the point here, but I'm looking for a way to be able to properly stop my containerized application while still being able to input commands from the keyboard.
My application could be simplified like that :
void gracefulStop() {
while (getThreadCount() > 1) { // this function exists somewhere else.
if (userInputThread.joinable()) {
userInputThread.join();
removeFromThreadCount(); // this function exists somewhere else.
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
exit(SUCCESS);
}
void sigTerm(int s) {
// Maybe do some stuff here, but what...
gracefulStop();
}
void userInputLoopThreadFunc() {
addToThreadCount(); // this function exists somewhere else.
while (keepGoing) {
char buf[4096];
if (!fgets(buf, sizeof(buf), stdin)) {
break; // we couldn't read from stdin, stop trying.
}
std::string input = std::string(buf); // we received a command
// Intercept exit command
if (input.starts_with("exit")) {
keepGoing = false;
}
// IRL there's thread safety
userInputQueue.push(input); // this will be processed by mainLoop() later
}
}
int main(int argc, char **argv) {
// Register the signal
signal(SIGTERM, sigTerm);
// Begin listening to user input
userInputThread = std::thread(&userInputLoopThreadFunc, this);
// this mainLoop function contains the core of the application
// as well as the processing code of the user input
mainLoop();
// if mainLoop function returned, we received the 'exit' command
gracefulStop();
}
I've read multiple question/answers like this one about non-blocking user input (the accepted answer advises to use a dedicated thread for input, which is what I am doing), or this other one about how to stop reading stdin, and the accepted answer seems promising but :
using ncurses for what I'm trying to do seems really overkill
If using select() and the timeout mechanism described, what would happen if the timeout occurs while typing a command?
Also I've read about the c++20 jthread here :
The class jthread represents a single thread of execution. It has the same general behavior as std::thread, except that jthread automatically rejoins on destruction, and can be cancelled/stopped in certain situations.
But I'm not sure that would help me here.
I'm thinking about multiple possibilities to solve my issue :
Find a way to send a newline character to the stdin of my application without user interaction, would be hackish if at all possible but would probably unblock fgets.
Kill the thread, I understand killing a thread is considered a bad practice, but since the only thing I'm doing here is stopping the application, maybe I can live with that, would there be any side effect? How would I do that?
Rewriting user input in another way (unknown to me yet, jthread, something else?) that would allow sigTerm() to stop the application.
Maybe use ncurses (would that really help me to stop the application by receiving a signal?)
Go with select() and the timeout mechanism and live with the risk of an interrupted input
Give up on user input and have some vacation time.
You can close stdin in your signal handler. fgets will then return immediately (and presumably, return NULL).
The good news is that close is on the list of functions that are safe to call from a signal handler (it's a pretty restrictive list). Happy days.
There's an alternative based around EINTR, but it looks messy since you don't know for certain that fgets will actually return when it gets it.
Also, closing stdin should still work should you switch to using cin and getline, which would definitely improve your code (*). That probably returns and sets badbit when you close stdin, although the code can be made more robust than by checking for that alone. Perhaps just set a (volatile) flag in your signal handler and test that.
(*) Because getline can read into a std::string, which means it can read arbitrary long lines without worrying about allocating a fixed-size buffer that is 'big enough'.

linux prevent file descriptor from closing on program exit

I have a peculiar use case where on linux when using uinput http://thiemonge.org/getting-started-with-uinput, the process that creates the virtual input device, if it dies by default releases all open file descriptors.
In this case it also releases the created virtual input device and the device flat out disappears from /dev/input.
I am wondering if there is a simple solution to this problem, the most obvious being to not release the open file descriptor upon program termination. The more annoying one to spawn a proxy process to simply hold the FD.
I ended up going the proxy approach like so:
void main(int argc, char **argv) {
create_uinput_device();
print_eventn();
set_argv0_eventn();
if (fork()) {
return;
} else {
//hold the uinput fd
while(1) { sleep(1000); }
}
}
This way when we cat /proc/[p]/cmdline we can easily find the /dev/input/event[n] and which pid is currently holding it. We can memcpy the new cmdline to argv0. So this is kind of a hack around this.
Also conveniently when we run this program we return right away with the /dev/input/event[n] device we need to forward to qemu; due to the print.
To truly fix this someone needs to merge into qemu changes so qemu itself creates the virtual input device, this is quite complex due to the vast amount of options that can be passed. Regardless once figured out, the virtual input device created by uinput will live as long as the qemu instance.

How to force open file "silently" (minimized, not active) using c++ WinAPI functional?

In my WinAPI C++ application I am trying to open an audio file with the default system player using ShellExecuteEx:
int OpenFileWithDefaultProgram(const std::wstring& path, int showMode, HANDLE* hProc) {
SHELLEXECUTEINFO shInfo;
::ZeroMemory(&shInfo, sizeof(SHELLEXECUTEINFO));
shInfo.cbSize = sizeof(SHELLEXECUTEINFO);
shInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shInfo.hwnd = NULL;
shInfo.lpVerb = L"open";
shInfo.lpFile = path.c_str();
shInfo.nShow = showMode;
::ShellExecuteEx(&shInfo);
*hProc = shInfo.hProcess;
return (int)shInfo.hInstApp;
}
The OpenFileWithDefaultProgram function is called this way:
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
// Process error
} else {
// Some actions
}
However SW_SHOWMINNOACTIVE parameter is ignored by some players (e.g. MediaPlayerClassic HomeCinema - MPC HC), which leads to opening a player with changing the foreground window and even showing player window not minimized on some PCs.
The first question is: is it possible to force opening player in "silent" mode (minimized and not becoming active)?
I have also tried using GetForegroundWindow and SetForegroundWindow, which didn't help until I added Sleep right after OpenFileWithDefaultProgram (as I understand, the player needs some time to initialize and during this time the foreground window doesn't change):
HWND hWndForeground = GetForegroundWindow();
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
// Process error
} else {
Sleep(100);
SetForegroundWindow(hWndForeground);
// Some actions
}
This code restored the foreground window perfectly, but I do not like the constant I need to use as a parameter of Sleep function.
Consequently, the second question is: is it possible to "wake up" the thread at the exact moment when the player is initialized? Alternatively, how should I determine the time needed for player initialization (considering that the default player can be anything and take really different time to start)?
Note:
I tried calling WaitForSingleObject(hProc, INFINITE), it just doesn't finish waiting since the player is not terminating after the playback;
I tried calling WaitForInputIdle(hProc, INFINITE), it returns immediately without waiting (probably, since the player does not have a message queue).
The first question is: is it possible to force opening player in "silent" mode (minimized and not becoming active)?
No, the best you can do is request it, and requests can be ignored. You already discovered that part.
The second question: is it possible to "wake up" the thread at the exact moment when the player is initialized?
No, there's no moment defined when a process is fully initialized. You already discovered WaitForInputIdle and its restrictions. But imagine a media player that fetches a CD cover image in the background (not that far-fetched, no need to delay audio for that)—when does it finish initialization?
Also, keep in mind that ShellExecute might not even start a new process. If there is an existing one, it may use it to open the file.

Need help for explain a function in C++

I am doing simple version of pacman for c++. When I look up for some example in the internet, I found some code which I dont really understand. Please help me to explain it, grateful for that.
void GoToXY(int column, int line)
{
// Create a COORD structure and fill in its members.
// This specifies the new position of the cursor that we will set.
COORD coord;
coord.X = column;
coord.Y = line;
// Obtain a handle to the console screen buffer.
// (You're just using the standard console, so you can use STD_OUTPUT_HANDLE
// in conjunction with the GetStdHandle() to retrieve the handle.)
// Note that because it is a standard handle, we don't need to close it.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Finally, call the SetConsoleCursorPosition function.
if (!SetConsoleCursorPosition(hConsole, coord))
{
// Uh-oh! The function call failed, so you need to handle the error.
// You can call GetLastError() to get a more specific error code.
// ...
}
}
My questions are:
What does this line do? : HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
Why we have an empty if? And what is the point of an empty if statement?
The line you ask about gives you a file handler for the standard output. It is likely that below it is used to print something to the console, or may be to draw the actual Pacman game there.
Here's some documentation on it, that might be helpful:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682075(v=vs.85).aspx
With regard to your second question, empty if is usually pointless. In your particular case the author of the example just points out, that GetStdHandle can fail (which is highly unlikely in reality), and that you might want to handle it in some way (may be print some error message and gracefully exit), but he himself doesn't fill it in.
Now as you develop your game on top of that example you might either choose to ignore that error (in which case you might as well just remove that entire if block), or handle it in some way (in which case you would fill in the body of that if statement)
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetStdHandle(STD_OUTPUT_HANDLE) retrieves a HANDLE to the standard output (Which is usually the active console) see here
A HANDLE is pointer to anything. You can see here
Answer to your second and third question is, it is not necessary here to write an empty if statement. Control will go to the if statement, if the SetConsoleCursorPosition() function doesn't work correctly. So, you can handle your error in the if, and if u don't want to handle the error, leave the if statement empty.

How to create a partition without Windows assigning a drive letter?

I am trying to initialize and partition an attached virtual hard disk through the Windows API. I have been successful using DeviceIoControl() to do so, however whenever I apply the desired drive layout Windows is automatically assigning a drive letter to the partition and popping up an annoying "Would you like to format?" dialog.
My intent is to handle the formatting and mounting of this partition later in the program, but I'm not sure how to stop this behavior. I have tried setting RecognizedPartition to FALSE, but this seems to have no effect.
Relevant code:
Layout.PartitionStyle = PARTITION_STYLE_MBR;
Layout.PartitionCount = 4;
Layout.Mbr.Signature = MY_DISK_MBR_SIGNATURE;
Layout.PartitionEntry[0].PartitionStyle = PARTITION_STYLE_MBR;
Layout.PartitionEntry[0].PartitionNumber = 1;
Layout.PartitionEntry[0].StartingOffset.QuadPart = MY_DISK_OFFSET;
Layout.PartitionEntry[0].PartitionLength.QuadPart =
(Geom.DiskSize.QuadPart - MY_DISK_OFFSET);
Layout.PartitionEntry[0].Mbr.PartitionType = PARTITION_IFS;
Layout.PartitionEntry[0].Mbr.BootIndicator = FALSE;
Layout.PartitionEntry[0].Mbr.RecognizedPartition = FALSE;
Layout.PartitionEntry[0].Mbr.HiddenSectors =
(MY_DISK_OFFSET / Geom.Geometry.BytesPerSector);
for (int i = 0; i < 4; i++)
{
Layout.PartitionEntry[i].RewritePartition = TRUE;
}
if (!DeviceIoControl(hDisk, IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
Layout, dwLayoutSz, NULL, 0, &dwReturn, NULL))
{
// Handle error
}
DeviceIoControl(hDisk, IOCTL_DISK_UPDATE_PROPERTIES,
NULL, 0, NULL, 0, &dwReturn, NULL);
What can I do to prevent automatic drive letter assignment?
The only reliable way I could find to work around this issue was to stop the "Shell Hardware Detection" service while the volume was created and formatted. However, this approach is so unapologetically silly that I refused to put it into code.
Another "hackish" option is to have the service start up and then immediately spawn itself (or a "worker" executable) in a hidden window via CreateProcess() with the CREATE_NO_WINDOW flag.
Since this software runs as a system service and I'd rather not complicate the code for something that only happens once or twice over the lifetime of the system, I've just had to accept that sometimes there will occasionally be an Interactive Services Detection window pop up for a few moments while creating the partitions.
If anyone discovers a good method for preventing the format prompt while programmatically creating and formatting a drive, I'll happily change the accepted answer (and owe you a beer).
It's been awhile since I've used this API, but from memory you can't. But it's doesn't stop you from removing the drive letter assignment after the fact.
I'm not sure if it will stop the format prompt tho, all the times that I have done this the partition has already been formatted correctly before I do the disk layout update.
I just solved this problem, by waiting for several seconds for the drive to be available and then directly issue a format action. See my answer here.
Rufus has an interesting workaround: it installs a window event hook that detects the "do you want to format this drive?" prompts and immediately closes them. See source code here.
It then goes on to arrange to mount only the partitions it cares about, but that's orthogonal.