Entries for tag "winapi", ordered from most recent. Entry count: 21.
# How to programmatically check graphics driver version
Sat
16
Dec 2023
This article is for you if you are a graphics programmer who develops for Windows using Direct3D 11, 12, or Vulkan, and you want to fetch the version of the graphics driver currently installed in your user's system programmatically. If you are in a hurry, you can jump straight to the recommended solution in section "DXGI way" below. However, because this topic is non-trivial, I invite you to read the entire article, where I explain it comprehensively.
Comments | #rendering #directx #vulkan #windows #winapi Share
# Ways to Print and Capture Text Output of a Process
Sun
02
Jul 2023
In my previous blog post “Launching process programmatically: system vs CreateProcess vs ShellExecute”, I investigated various ways of launching a new process when programming in C++ using Windows, with the focus on different ways to specify a path to the executable file. Today, I want to describe a related topic: we will investigate ways that a process can print some text messages (standard output, standard error, WriteConsole
function, DebugOutputString
function), how we can observe this output and, finally, how we can capture it programmatically when launching a subprocess using CreateProcess
function.
Visual Studio / C++ project accompanying this article: github.com/sawickiap/TextOutputTest
Comments | #windows #winapi Share
# Launching process programmatically: system vs CreateProcess vs ShellExecute
Sat
15
Apr 2023
Today I went on a quest to investigate various ways in which we can launch a process (an EXE file) programmatically, while programming in C++ using Windows. I tested 3 different functions: system
, CreateProcess
, ShellExecute
. I focused on ways to specify a path to the executable file – not on passing parameters and not on capturing standard input/output of the subprocess (which I plan to investigate next and I did). All examples below launch a subprocess and wait until it completes before continuing. They all make the subprocess inheriting the console, so if both main process and the subprocess are console programs, their output will go to the single console of the main process.
But first things first: To understand this article, please recall that in operating systems we commonly use, no matter if Windows or Linux, every executable file launched as a process has several parameters:
Paths in the file system can be absolute (in case of Windows it usually means they start with drive letter, like “C:\Dir1\Text.exe”) or relative.
Startup directory is often the same as the directory where the executable file is located, but it doesn’t need to be. Many methods of process launching offer an explicit parameter for it. We won’t use it in the code samples below, but you can also achieve this manually from system console. For example, following console command uses a relative path to launch an executable located in “C:\Dir2\Test.exe”, while current directory of the process will be the same as current directory of the console: “C:\Dir1”:
C:\Dir1>..\Dir2\Test.exe
Method 1: Function system from standard C library (required header: <stdlib.h>
or <cstdlib>
in C++) is the simplest, most primitive one. It just takes a single string as parameter. An advantage of it is that you can launch any console command with it, also built-in commands (like “echo”), not only EXE files. It is also portable between different operating systems.
#include <cstdlib>
int main()
{
char path[MAX_PATH];
strcpy_s(path, "Test.exe");
system(path);
}
Waiting for the command to finish is the default behavior of this function and so is inheriting the console, so that messages printed to the standard output by “Test.exe” will go to the same console as our host application.
path
can always be absolute or relative. For each of the 4 methods described in this article, I found answers to following questions:
strcpy_s(path, "C:\\My Program\\Test.exe");
? No. (Note the double backslash \\
is for escaping in C++, so that string will actually contain single backslashes. You can also use forward slashes /
in Windows – they work with all methods described in this article and they don’t need to be escaped in C++ code.)strcpy_s(path, "\"C:\\My Program\\Test.exe\"");
? Yes.^
, like strcpy_s(path, "C:\\My^ Program\\Test.exe");
? Yes! (However strange it looks, this is the character used as an escape sequence in Windows shell!)Method 2: Function CreateProcess from WinAPI (required header: <Windows.h>
) is likely the most native and most feature-rich option. Numerous parameters passed to the function and accompanying structures allow to control the new subprocess in various ways, including getting and using its process handle or capturing its standard input/output. Here, for simplicity, I replicate the behavior of system
function from method 1 – I make it inherit the console by passing parameter bInheritHandles = TRUE
and wait until it completes by calling WaitForSingleObject
on the process handle. Process handle and main thread handle also need to closed to avoid resource leak.
STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION processInfo = {};
BOOL success = CreateProcess(
path, // lpApplicationName
NULL, // lpCommandLine
NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
TRUE, // bInheritHandles
0, // dwCreationFlags
NULL, // lpEnvironment
NULL, // lpCurrentDirectory
&startupInfo,
&processInfo);
assert(success);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
There are actually 2 ways to pass executable file path to CreateProcess
. Code above shows the first way – using lpApplicationName
parameter, which is intended for just application name, while command line parameters are passed via next argument. Note this is different from system
function, which accepts one string with everything. Using the method shown above:
"C:\\My Program\\Test.exe"
? Yes – likely because this parameter is intended exclusively for executable file path."\"C:\\My Program\\Test.exe\""
? No.^
, like "C:\\My^ Program\\Test.exe"
? No.Method 3: Function CreateProcess, but this time passing executable file path as lpCommandLine
parameter, while leaving lpApplicationName
set to NULL
. This is also a valid use case and it behaves differently – more like launching a console command than starting a specific EXE file.
STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION processInfo = {};
BOOL success = CreateProcess(
NULL, // lpApplicationName <- !!!
path, // lpCommandLine <- !!!
NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
TRUE, // bInheritHandles
0, // dwCreationFlags
NULL, // lpEnvironment
NULL, // lpCurrentDirectory
&startupInfo,
&processInfo);
assert(success);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
"C:\\My Program\\Test.exe"
? No!"\"C:\\My Program\\Test.exe\""
? Yes.^
, like "C:\\My^ Program\\Test.exe"
? No!Method 4: Function ShellExecuteEx (or legacy ShellExecute
) which is also part of WinAPI, but coming from header <shellapi.h>
. It requires COM to be initialized with CoInitializeEx
. It can be used not only to start processes from EXE files, but also to open any types of files (TXT or DOCX documents, JPEG images etc.) with their associated programs, as if the user double-clicked on such file or right-clicked and selected one of the available “verbs”, like “Edit” or “Print”. But for this article, let’s focus on launching executable files. To replicate the same behavior as in previous methods, I pass SEE_MASK_NO_CONSOLE
to inherit console and SEE_MASK_NOCLOSEPROCESS
to retrieve process handle to be able to wait for it.
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
SHELLEXECUTEINFO shellExecuteInfo = {
.cbSize = sizeof(SHELLEXECUTEINFO),
.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
.lpFile = path,
.nShow = SW_SHOWNORMAL
};
BOOL success = ShellExecuteEx(&shellExecuteInfo);
assert(success);
WaitForSingleObject(shellExecuteInfo.hProcess, INFINITE);
CloseHandle(shellExecuteInfo.hProcess);
This method behaves in the following way:
"C:\\My Program\\Test.exe"
? Yes."\"C:\\My Program\\Test.exe\""
? Yes.^
, like "C:\\My^ Program\\Test.exe"
? No.To summarize, let’s see all the results in a table:
system() | CreateProcess() lpApplicationName |
CreateProcess() lpCommandLine |
ShellExecuteEx() | |
---|---|---|---|---|
Works without extension? "Test" |
Yes | No | Yes | Yes |
Searching dir of the host app? | No | No | Yes | No |
Searching current dir? | Yes | Yes | Yes | Yes |
Searching PATH env var? | Yes | No | Yes | Yes |
Path with spaces unescaped: My Program\Test.exe |
No | Yes | No | Yes |
Path with spaces enclosed with quotes: "My Program\Test.exe" |
Yes | No | Yes | Yes |
Spaces escaped with ^ : My^ Program\Test.exe |
Yes | No | No | No |
I did my tests using Windows 10, Version 22H2 (OS Build 19045.2846) and Visual Studio 2022 17.5.3. Although unlikely, it is not impossible that these results may change on another version of the operating system or C++ compiler and standard library implementation.
Comments | #windows #c++ #winapi Share
# When QueryPerformanceCounter call takes long time
Sun
03
Dec 2017
QueryPerformanceCounter function is all about measuring time and profiling performance, so I wasn't able to formulate right Google query to find a solution to the problem I had - call to QueryPerformanceCounter
function itself taking too much time. Below I describe what I eventually found out.
It all started from hardware failure. My motherboard stopped working, so I needed to buy a new one (ASRock X370 Killer SLI). I know that normally changing motherboard requires reinstalling Windows, but I tried not to do it. The system didn't want to boot, so I booted the PC using pendrive with Windows installer and launched the repair function. It helped - after that Windows was able to start and everything seemed to work... until I launched the program that I develop on that machine. It was running painfully slow.
I tried different things to find out what is happening. Input/output to hard drive or network was not an issue. GPU performance was also OK. It seemed that the app is just doing its calculations slowly, like the CPU was very slow. I double-checked actual CPU and RAM frequency, but it was OK. Finally I launched sampling profiler (the one embedded in Visual Studio - command: Analyze > Performance Profiler). This way I found that most of the time is spent in function QueryPerformanceCounter
.
This WinAPI function is the recommended way to obtain a timestamp in Windows. It's very precise, monotonic, safe to use on multiple cores and threads, it has stable frequency independent of CPU power management or Turbo Boost... It's just great, but in order to meet all these requirements, Windows may use different methods to implement it, as described in article Acquiring high-resolution time stamps. Some of them are fast (just reading TSC register), others are slow (require system call - transition to kernel mode).
I wrote a simple C++ program that tests how long it takes to execute QueryPerformanceCounter
function. You can see the code here: QueryPerformanceCounterTest.cpp and download 64-bit binary here: QueryPerformanceCounterTest.zip. Running this test on two different machines gave following results:
CPU: Intel Core i7-6700K, Motherboard: GIGABYTE Z170-HD3-CF:
> QueryPerformanceCounterTest.exe 1000000000
Executing QueryPerformanceCounter x 1000000000...
According to GetTickCount64 it took 0:00:11.312 (11.312 ns per call)
According to QueryPerformanceCounter it took 0:00:11.314 (11.314 ns per call)
CPU: AMD Ryzen 7 1700X, Motherboard: ASRock X370 Killer SLI (changed from different model without system reinstall):
> QueryPerformanceCounterTest.exe 10000000
Executing QueryPerformanceCounter x 10000000...
According to GetTickCount64 it took 0:00:24.906 (2490.6 ns per call)
According to QueryPerformanceCounter it took 0:00:24.911 (2491.1 ns per call)
As you can see, the function takes 11 nanoseconds on first platform and 2.49 microsenonds (220 times more!) on the second one. This was the cause of slowness of my program. The program calls this function many times.
I tried to fix it and somehow convince Windows to use the fast implementation. I uninstalled and reinstalled motherboard drivers - the latest ones downloaded from manufacturer website. I upgraded and downgraded BIOS to different versions. I booted the system from Windows installation media and "repaired" it again. I restored default settings in UEFI/BIOS and tried to change "ACPI HPET Table" option there to Disabled/Enabled/Auto. Nothing worked. Finally I restored Windows to factory settings (Settings > Update & Security > Recovery > Reset this PC). This solved my problem, but unfortunately it's like reinstalling Windows from scratch - now I need to install and configure all the apps again. After that the function takes 22 ns on this machine.
My conclusions from this "adventure" are twofold:
QueryPerformanceCounter
to execute slowly on some platforms, like for 2.5 microseconds. If you call it just once per rendering frame then it doesn't matter, but you shouldn't profile every small portion of your code with it, calling it millions of times.Update 2017-12-11: A colleague told me that enabling/disabling HPET using "bcdedit" system command could possibly help for that issue.
Update 2018-12-17: Blog post "Ryzen Threadripper for Game Development – optimising UE4 build times" on GPUOpen.com, section "HPET timer woes", seems to be related to this topic.
Comments | #windows #optimization #hardware #winapi Share
# Lost clicks and key presses on low FPS
Sun
22
Oct 2017
There is a problem with handling input from mouse and keyboard in games and other interactive applications that I just solved. I would like to share my code for the solution. When your app uses a loop that constantly calculates and renders frames, like games usually do, it may seem natural to just read current state of every mouse and keyboard key (whether it's down or up) on each frame. You may then caculate derived information, like whether a button has just been pressed on released, by comparing new state to the state from previous frame. This is how Dear ImGui library works. So first solution could look like this:
void UpdateFrame() { // Fill ImGui::GetIO().DeltaTime, KeyCtrl, KeyShift, KeyAlt etc. ImGui::GetIO().MouseDown[0] = (GetKeyState(VK_LBUTTON) & 0x8000) != 0; ImGui::GetIO().MouseDown[1] = (GetKeyState(VK_RBUTTON) & 0x8000) != 0; ImGui::GetIO().MouseDown[2] = (GetKeyState(VK_MBUTTON) & 0x8000) != 0; for(uint32_t i = 0; i < 512; ++i) ImGui::GetIO().KeysDown[i] = (GetKeyState(i) & 0x8000) != 0; ImGui::NewFrame(); if(ImGui::IsKeyPressed('A')) // Do something... }
There is one problem with this approach. If user presses and releases a key for a very short time, so that both press and release happens between two frame, it will go unnoticed. This is very annoying. It happens especially when:
First step towards solving this is to react to "real" events that are sent by the operating system:
Comments | #gui #winapi #windows Share
# Handling Multiple Mice with Raw Input
Thu
21
Mar 2013
When you connect second USB mouse to your computer, you don't have second cursor to move on the screen and click on things. Instead you can move and click the single cursor with both mice. What if you want to distinguish messages from multiple mice in your program? I found the solution here. I downloaded and looked at the source code of MouseParty.zip linked from this page.
Handling multiple mice is possible using part of WinAPI called Raw Input. If you have <Windows.h> included, have your WinAPI window and message loop, you only need to initialize Raw Input like this:
RAWINPUTDEVICE device;
device.usUsagePage = 0x01;
device.usUsage = 0x02;
device.dwFlags = 0;
device.hwndTarget = 0;
RegisterRawInputDevices(&device, 1, sizeof device);
You then start to receive WM_INPUT message, which should be handled this way:
case WM_INPUT:
OnRawInput(
GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT,
(HRAWINPUT)lParam);
// Must call DefWindowProc!
break;
# Easiest Way to Generate a Bitmap
Wed
19
Oct 2011
I wanted to visualize results of some mathematical computations so I wondered what is the easiest way to generate and then show or save a bitmap? I considered Scilab, PHP with GD library, C++ with WinAPI GDI, C++ with some library that have image file formats support like FreeImage... Finally I've came up with the following solution, using only C++ and WinAPI to fill appropriate data structures and save the image as 24-bit BMP file.
// Width and height of the bitmap unsigned size_x = 1280, size_y = 720; // Rows top-down, // for each row pixels from left to right, // for each pixel components B, G, R = 0..255. unsigned data_size = size_x * size_y * 3; unsigned char *data = new unsigned char[data_size]; // Here fill the data, for example: for (unsigned y = 0, i = 0; y < size_y; ++y) { for (unsigned x = 0; x < size_x; ++x) { data[i++] = 255; // G data[i++] = 255; // B data[i++] = 255; // R } } // Prepare data structures DWORD data_offset = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); DWORD file_size = data_offset + data_size; BITMAPFILEHEADER file_header = { 0x4D42, // bfType = "BM" file_size, // bfSize 0, 0, // bfReserved1, bfReserved2 data_offset, // bfOffBits }; BITMAPINFOHEADER info_header = { sizeof(BITMAPINFOHEADER), // biSize (LONG)size_x, -(LONG)size_y, // biWidth, biHeight 1, // biPlanes 24, // biBitCount BI_RGB, // biCompression 0, // biSizeImage 72, 72, // biXPelsPerMeter, biYPelsPerMeter 0, 0, // biClrUsed, biClrImportant }; // Save file FILE *file = fopen("file_name.bmp", "wb"); fwrite(&file_header, sizeof(file_header), 1, file); fwrite(&info_header, sizeof(info_header), 1, file); fwrite(&data[0], 1, data_size, file); fclose(file); // Finalize delete [] data;
Comments | #rendering #winapi #c++ Share
# Handling Ctrl+C in Windows Console Application
Wed
28
Sep 2011
Just a small code snippet: Let's say you write a console application in native C++ for Windows. Closing the console by pressing Ctrl+C, Ctrl+Break or clicking on close window button [X] kills the process. Is there any way to handle such event and close the program gracefully? The answer is calling SetConsoleCtrlHandler() WinAPI function and implementing your own HandlerRoutine callback function. The template looks like this:
// Handler function will be called on separate thread! static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType) { switch (dwCtrlType) { case CTRL_C_EVENT: // Ctrl+C break; case CTRL_BREAK_EVENT: // Ctrl+Break break; case CTRL_CLOSE_EVENT: // Closing the console window break; case CTRL_LOGOFF_EVENT: // User logs off. Passed only to services! break; case CTRL_SHUTDOWN_EVENT: // System is shutting down. Passed only to services! break; } // Return TRUE if handled this message, further handler functions won't be called. // Return FALSE to pass this message to further handlers until default handler calls ExitProcess(). return FALSE; } int main(int argc, char **argv) { SetConsoleCtrlHandler(console_ctrl_handler, TRUE); ... }
If your program performs some loop and you want the user to be able to break it by closing the console or pressing Ctrl+C, you can solve it this way:
static volatile bool g_exit = false; static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType) { g_exit = true; return TRUE; } int main(int argc, char **argv) { SetConsoleCtrlHandler(console_ctrl_handler, TRUE); initialize(); while (!g_exit) do_a_piece_of_work(); finalize(); }