I'm trying to create a simple non-blocking timer in C++ that can be reset. I've google searched for a while to find some code examples but everything I find is either too complicated to understand or does not compile without extra non example code.
I have a program that logs a key press to a file, but I want this file to be written over one seconds after the key has been pressed unless another key has been pressed before the second is up.
I believe I should use Win32 timers, (I am using windows) however I can't find a simple compilable example of their use.
for example this method taken from the info page:
SetTimer(hwnd, // handle to main window
IDT_TIMER1, // timer identifier
1000, // 1-second interval
(TIMERPROC) MyTimerProc); // no timer callback
VOID CALLBACK MyTimerProc(
HWND hwnd, // handle to window for timer messages
UINT message, // WM_TIMER message
UINT idTimer, // timer identifier
DWORD dwTime) // current system time
{
// my proceedure code
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen("LOG.TXT", "w");
fprintf(OUTPUT_FILE, "%s", "");
fclose(OUTPUT_FILE);
// writes a blank text file.
KillTimer(hwnd, IDT_TIMER1); // stop timer after one call
}
doesn't compile because the IDT_TIMER1 hasnt' been defined I think.
Also, I'm not sure if this would be reset by calling it twice or would just start two separate calls 1 second apart.
Any help greatly appreciated.
Just use the Hardware Performance Timer, which can be quickly found via google, or if you want something more cross platform use the timegettime method, which can also be found via google, neither need a Win32 message loop.
You are responsible for giving ID_TIMER1 a value. I believe you (99%) also have to have a windows message loop for it to work.
Here are a couple of minimal, compilable examples.
The following console program works. It sets a timer using SetTimer
then loops in a message loop. The message loop receives and processes WM_TIMER messages
and the timer callback also is called for each time interval. And it does not block.
#define STRICT 1
#include <windows.h>
#include <iostream.h>
VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
cout << "Time: " << dwTime << '\n';
cout.flush();
}
int main(int argc, char *argv[], char *envp[])
{
int Counter=0;
MSG Msg;
UINT TimerId = SetTimer(NULL, 0, 500, &TimerProc); //SetTimer
cout << "TimerId: " << TimerId << '\n';
if (!TimerId)
return 16;
while (GetMessage(&Msg, NULL, 0, 0))
{
++Counter;
if (Msg.message == WM_TIMER)
cout << "Counter: " << Counter << "; timer message\n";
else
cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
DispatchMessage(&Msg);
}
KillTimer(NULL, TimerId);
return 0;
}
You don't need a window or even an event loop. Look at the WaitForSingleObject function.
Here is some code
HANDLE hStdin;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen("LOG.TXT", "w");
bool previous_input_written = TRUE;
switch (WaitForSingleObject(hStdin, 1000) {
case WAIT_OBJECT_0:
// input happened on hStdin
if (!previous_input_written) {
// the previous input was not saved to file
fprintf(OUTPUT_FILE, ...
previous_input_written= TRUE;
}
ReadConsoleInput(hStdin, ...
previous_input_written = FALSE;
case WAIT_TIMEOUT:
// the 1000ms delay timed out, write to file
fprintf(OUTPUT_FILE, ...
previous_input_written= TRUE;
}
fclose(OUTPUT_FILE);
Related
I tried to implement a basic hook under windows.
While it technically works (my handle gets called) it produces massive bugs, that i do not know how to fix.
When I run the programm and try to write something in the firefox.exe searchbar or the explorer.exe addres bar the programs crash.
That is the code i currently tried. I stripped everything unnecessary but it still doesnt work
main.cc
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <shellapi.h>
int main (int argc, char** argv){
HINSTANCE dll = NULL;
HOOKPROC proc = NULL;
HHOOK hook = NULL;
MSG msg;
BOOL b_ret = FALSE;
dll = LoadLibraryA("hookdll.dll");
if (dll == NULL) {
std::cerr << "WinAPI Error: " << GetLastError() << "\n";
return 1;
}
proc = (HOOKPROC)GetProcAddress(dll, "KeyboardHook");
if (proc == NULL) {
FreeLibrary(dll);
std::cerr << "WinAPI Error: " << GetLastError() << "\n";
return 1;
}
hook = SetWindowsHookEx(WH_CALLWNDPROC, proc, dll, 0);
if (hook == NULL) {
FreeLibrary(dll);
std::cerr << "WinAPI Error: " << GetLastError() << "\n";
return 1;
}
while (GetMessage(&msg, NULL, WH_KEYBOARD, WM_KEYLAST) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hook);
FreeLibrary(dll);
return 0;
}
And in the DLL:
hooks.h
#ifndef __LOG_DLL_HOOKS_H__
#define __LOG_DLL_HOOKS_H__
#include <iostream>
#include <fstream>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
extern "C" LRESULT CALLBACK KeyboardHook(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam);
#endif // !__LOG_DLL_HOOKS_H__
hooks.cc
#include "Hooks.h"
extern "C" LRESULT CALLBACK KeyboardHook(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam) {
if (code == HC_ACTION) {
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
As you can see it barely does anything.
I worked with the official windows docs and did everything the right way (or so i thought)
The only thing that could make a difference is the return value of KeyboardHook, but
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644984(v=vs.85) states that:
If code is less than zero, the hook procedure must return the value returned by CallNextHookEx.
If code is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns;
I read that as: "Return CallNextHookEx either way", which i did.
Thanks for any answeres
Well, for starters, why are you using a keyboard function for a window procedure hook? I think you meant to use WH_KEYBOARD instead of WH_CALLWNDPROC when calling SetWindowsHookEx().
Also, your GetMessage() call is wrong, because WH_KEYBOARD is not a message identifier. You would need to use WM_KEYFIRST instead, to match your use of WM_KEYLAST (since you are clearly only interested in dispatching keyboard messages).
However, you are setting the dwThreadId parameter of SetWindowsHookEx() to 0, which means you are hooking not just your own thread but all threads of all processes globally. A WH_KEYBOARD hook runs in the context of the thread that installs it, which means internally the OS will have to delegate the hooked keyboard messages of those other threads to your thread, and it does that by sending messages to your thread. But, your message loop is not going to be processing any of those messages because it is filtering for only keyboard messages (of which it will never receive, since your thread has no UI of its own).
With all of that said, try this instead:
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <shellapi.h>
int main (){
HINSTANCE dll = LoadLibraryA("hookdll.dll");
if (dll == NULL) {
std::cerr << "WinAPI Error: " << GetLastError() << "\n";
return 1;
}
HOOKPROC proc = (HOOKPROC) GetProcAddress(dll, "KeyboardHook");
if (proc == NULL) {
std::cerr << "WinAPI Error: " << GetLastError() << "\n";
FreeLibrary(dll);
return 1;
}
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, proc, dll, 0);
if (hook == NULL) {
std::cerr << "WinAPI Error: " << GetLastError() << "\n";
FreeLibrary(dll);
return 1;
}
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hook);
FreeLibrary(dll);
return 0;
}
When, I open some of the software applications I have to wait 2-3 seconds until window will show on desktop. I have to use Sleep(2000); and then call method set always on top. I'm trying to replace Sleep in my code. I would like to get signal from opened window and after this, call a method, which allows opened window be always on top.
Here's my code:
BOOL CALLBACK EnumWindowsProc(HWND windowHandle, LPARAM lParam)
{
DWORD searchedProcessId = (DWORD)lParam;
DWORD windowProcessId = 0;
GetWindowThreadProcessId(windowHandle, &windowProcessId);
cout << "Process id: " << windowProcessId << endl;
if(searchedProcessId == windowProcessId) {
HWND hwnd = windowHandle;
Sleep(2000);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
cout << "Process ID found!" << endl;
return TRUE;
}
return TRUE;
}
void AlwaysOnTop(int processId)
{
EnumWindows(&EnumWindowsProc, (LPARAM)processId);
}
void AlwaysOnTop(char *name)
{
cout << "String: " << name << endl;
Sleep(2000);
HWND h = FindWindow(NULL, (LPCSTR) name);
SetActiveWindow(h);
SetForegroundWindow(h);
SetWindowPos(h, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
}
int main()
{
char s[] = {"Application"};
AlwaysOnTop(s);
//AlwaysOnTop(2307);
system("PAUSE");
return 0;
}
Probably the best you can do is to call WaitForInputIdle:
Waits until the specified process has finished processing its initial input and is waiting for user input with no input pending, or until the time-out interval has elapsed.
This is the closest you can get to a general way to wait until a process is showing its UI. It won't always do what you want, but it's the best there is.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I created a system wide hook DLL and in my DLL I am trying to get notified each time a new process is created or destroyed. Whenever a new process is being detected, I want to be able to send a message to the calling program, be it a Boolean value or a custom object.
How can I do this? At the moment I am using a file to log all names, which is horrible. This is the code so far:
def file
;LIBRARY
; Def file
EXPORTS
InstallHook
UninstallHook
dllapi.h
void InstallHook(void);
void UninstallHook(void);
dllmain.cpp
#include "stdafx.h"
using namespace std;
HINSTANCE currentProcessHandle;
HHOOK hookID;
string str = "1";
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
currentProcessHandle = hModule;
return TRUE;
}
LRESULT CALLBACK HookProcedure(int nCode, WPARAM wparam, LPARAM lparam)
{
if (nCode < 0) return CallNextHookEx(hookID, nCode, wparam, lparam);
std::ofstream outfile;
CBT_CREATEWND *CBTHOOKCREATE;
RECT *CBTRECTPTR;
RECT CBTRECT;
wstring Message;
CBTHOOKCREATE = (CBT_CREATEWND*) lparam;
LPWSTR str = L" ";
outfile.open(("d:\\test.txt"), std::ios_base::app);
if (nCode >= 0) {
switch (nCode)
{
case HCBT_CREATEWND:
outfile << *(CBTHOOKCREATE->lpcs->lpszName) << " " << CBTHOOKCREATE->lpcs->lpszName << " Created!~ " << endl;
//cout << "Created!~" << endl;
break;
case HCBT_DESTROYWND:
outfile << "Destroyed!~" << endl;
//cout << "Destroyed!~" << endl;
break;
default:
//cout << "something else" << endl;
break;
}
}
outfile.close();
return 0;
}
void InstallHook(void)
{
hookID = SetWindowsHookEx(WH_CBT, HookProcedure, currentProcessHandle, 0);
}
void UninstallHook(void)
{
UnhookWindowsHookEx(hookID);
}
Hook Consumer console application
// Hook Executer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "..\Dll\dllapi.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int num = -1;
cout << "1.Install Hook"<<endl
<< "2.Unistall Hook"<<endl
<< "0.Exit";
do{
cin >> num;
if (num ==1)
{
InstallHook();
}
else
{
UninstallHook();
}
getchar();
system("cls");
cout << "1.Install Hook" << endl
<< "2.Unistall Hook" << endl
<< "0.Exit";
} while (num != 0 && num < 3);
return 0;
}
The Hook DLL is loaded, by Windows, in the address spaces on the hooked processes. You will have to use IPC. See Interprocess Communications for a starter.
One simple IPC, usable in such a case, may be Data Copy.
Note that Data Copy requires an active (pumped) message queue in the receiving thread.
One possible way to implement that (many others possible):
You add a secondary thread to your EXE, with a pumped message queue. In the new thread, you will create a dummy invisible windows, with a specific class name.
The code for that is a very classic sequence: RegisterClass, CreateWindow, while GetMessage DispatchMessage
In the Hook DLL, you will have a global HWND variable. When wanting to use WM_COPYDATA, if the global variable is null, use FindWindow to retrieve the HWND, and store it for next use. That code will be executed a least one time in each hooked process.
You may want to use the SendMessageTimeout API to send the WM_COPYDATA message.
Note that if you stop/restart your exe quickly, some processes may have an invalid HWND stored in the global variable. Check the return value of the Send API, and if it's "invalid hwnd", redo the FindWindow. (not sure if that's kind of behavior is really possible, but anyway...)
Also note, that your main thread should wait for the correct creation of the dummy window in the secondary thread before installing the hook.
If your hooking EXE is a Windowed one, you don't need a secondary thread, but you will have to build a GUI. You could also, perhaps, stay with "only one thread" and manage to juggle with some APIs, to have at the same time an active message queue and your getchar code, but I don't recommend that.
I'll preface this with saying that I am new to win32 programming.
I'm creating a global keyboard hook using a .dll, I have put in install and uninstall functions to handle the actual setting and removing of the keyboard hook.
#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
static HHOOK hk=NULL;
//static CMyFile *pLF;
#pragma data_seg()
HINSTANCE hins = NULL;
__declspec( dllexport ) LRESULT Install(){
std::cout << "Installing" << std::endl;
hk = SetWindowsHookEx(WH_KEYBOARD_LL,EventAnalysis::KeystrokeAnalysis::KeyboardCallback,hins,0);
if(hk == NULL){
std::cout << "Hook creation failed! - " << GetLastError() << std::endl;
}
return 0;
}
__declspec(dllexport) BOOL CALLBACK UnInstall()
{
std::cout << "UnInstalling" << std::endl;
return UnhookWindowsHookEx(hk);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hins = (HINSTANCE) hModule;
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
So now that I have my .dll, I created a simple executable that loads the library and installs the hooks:
int _tmain(int argc, _TCHAR* argv[])
{
auto funHandle = LoadLibrary(L"C:\\Users\\tprodanov\\Documents\\visual studio 2010\\Projects\\HaveFun\\Release\\HaveFun.dll");
if(funHandle == NULL){
std::cout << "Library load failed! - " << GetLastError() << std::endl;
}
auto Install = (LRESULT(*)()) GetProcAddress(funHandle, "?Install##YAJXZ");
if(Install == NULL){
std::cout << "Procedure load failed! - " << GetLastError() << std::endl;
}
Install();
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
auto Uninstall = (BOOL(*)()) GetProcAddress(funHandle, "?UnInstall##YGHXZ");
if(Uninstall == NULL){
std::cout << "Procedure load failed! - " << GetLastError() << std::endl;
}
Uninstall();
return 0;
}
What I find curious is that the behavior of my program is as expected in its current state (and also if instead of a message loop I just pop out a MessageBox() that waits for the user to click OK), but it doesn't work if I use std::cin.get() or an empty while loop. Can someone please explain why this is the behavior?
Also as a followup question - the KeyboardCallback function just prints to the console "Key Pressed".
LRESULT CALLBACK EventAnalysis::KeystrokeAnalysis::KeyboardCallback(int nCode, WPARAM wParam, LPARAM lParam){
std::cout << "Key pressed" << std::endl;
return CallNextHookEx(NULL,nCode,wParam,lParam);
}
I expected that this will be printed only when I press keys when focused on the console window, but even if I type in notepad the "Key Pressed" messages show up in my executable that called the Install function of the .dll. I don't understand this, since as far as I understood the dynamic library is loaded independently in every process, so every process has its own copy of the KeyboardCallback function and it will try to print to the foreground window's console.
The documentation makes it clear what is happening:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
The hook is installed by the call you made to Install. And so in the same thread that makes that call you need to run a message loop.
As for why showing a message box influences things, a message box operates by running a modal message loop. And that message loop will dispatch the hook messages.
And for the followup question, again the documentation has the answer:
The system calls this function every time a new keyboard input event is about to be posted into a thread input queue.
When it says posted into a thread input queue it means any thread input queue.
Or in the remarks to the documentation of SetWindowsHookEx look at the list of the various hook types, and their scope. The WH_KEYBOARD_LL is listed as a global hook.
Note also that WH_KEYBOARD_LL is a low-level hook and so does not result in the DLL being injected into another process. In fact your code is overly complex. You simply do not need a DLL here at all. You can get it all going with a call to SetWindowsHookEx from your executable that passes a callback function in that same executable.
Here's a minimal sample program that demonstrates all this:
#include <Windows.h>
#include <iostream>
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
std::cout << "Key pressed" << std::endl;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main(int argc, char* argv[])
{
std::cout << "Installing" << std::endl;
HHOOK hk;
hk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
std::cout << "UnInstalling" << std::endl;
UnhookWindowsHookEx(hk);
return 0;
}
I have been working on an application to set the desktop background basing of another application I found here: http://www.optimumx.com/downloads.html#SetWallpaper. The idea is to set the background to a wallpaper every 10 minutes, so it launches the SetWallpaper.exe with the command 'SetWallpaper.exe /D:S Wallpaper.jpg' but when I launch my application it creates a console window that doesn't automatically close and when I manually close it, it kills the exe.
#include <windows.h>
int main() {
int i = 1;
int j = 3;
// refresh = time until refresh in minutes
int refresh = 10;
// 1000 milliseconds = 1 second
int second = 1000;
int minute = 60;
int time = second * minute * refresh;
while (i < j) {
system("cmd /c start /b SetWallpaper.exe /D:S Wallpaper.jpg");
Sleep(time);
}
return 0;
}
I tried using 'sleep.exe' that comes with MinGW Msys but that creates a new process each team, eventually hogging all the processes.
Thanks in advance!
The first problem you're having is that you've created your program as a console application with a main method. Instead, create it as a Win32 Project with a WinMain entry point. This will be invoked directly without creating a console window.
EDIT: The second issue is addressed by Ferruccio's answer in that you're invoking another console application from yours which will also result in a console window being created.
You're going about it the hard way. It's fairly simple to change the Windows wallpaper in a program:
#include <windows.h>
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID) "path/to/wallpaper.jpg", SPIF_UPDATEINIFILE);
In any case, if you insist on launching an external program to do it. Use CreateProcess. It has the ability to launch console mode apps without a visible window, by setting the dwCreationFlags parameter to CREATE_NO_WINDOW.
Set ShowWindow to false and don't forget to FreeConsole at the end.
#include <windows.h>
int main(void)
{
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
// put your code here
system("cmd /c start /b SetWallpaper.exe /D:S Wallpaper.jpg");
FreeConsole();
return 0;
}
And as Ferruccio mentioned, You can use SetTimer and SystemParametersInfo to trigger a change periodically.
#define STRICT 1
#include <windows.h>
#include <iostream.h>
VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
LPWSTR wallpaper_file = L"C:\\Wallpapers\\wallpaper.png";
int return_value = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, wallpaper_file, SPIF_UPDATEINIFILE);
cout << "Programmatically change the desktop wallpaper periodically: " << dwTime << '\n';
cout.flush();
}
int main(int argc, char *argv[], char *envp[])
{
int Counter=0;
MSG Msg;
UINT TimerId = SetTimer(NULL, 0, 2000, &TimerProc); //2000 milliseconds = change every 2 seconds
cout << "TimerId: " << TimerId << '\n';
if (!TimerId)
return 16;
while (GetMessage(&Msg, NULL, 0, 0))
{
++Counter;
if (Msg.message == WM_TIMER)
cout << "Counter: " << Counter << "; timer message\n";
else
cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
DispatchMessage(&Msg);
}
KillTimer(NULL, TimerId);
return 0;
}