What is the proper method of blocking premature termination of a Win32 Console Application running on Windows 7?
When Vista was introduced, there were changes regarding how Application Shutdown happened. Contrary to the behavior in XP, which was to open up a UI requesting whether the user wants to force close or not, Windows Vista (and 7) terminates the process if nothing is done programmatically to prevent it. Console apps and applications without a top level window visible must also use the new function ShutdownBlockRequestCreate to provide a reason for Vista to show in the UI that pops up or it will terminate the program after 5 seconds anyway.
Below is my attempt at using the ShutdownBlockRequestCreate function in a Win32 Console application; the precompiled header option was removed from the project after creation by the wizard. I get the error code of 5, corresponding to ERROR_ACCESS_DENIED, whenever I use the function. This is apparently (according to the Application Shutdown link) because I am not calling the function from the same thread as was used to create the window (the console window).
#include <iostream>
#include <tchar.h>
#include <conio.h>
#include <windows.h>
typedef BOOL (WINAPI *SBRCREATEFUNC)(HWND,LPCWSTR);
void RegisterShutdownBlockReason() {
SBRCREATEFUNC ShutdownBlockReasonCreate;
HWND hWnd = GetForegroundWindow();
HINSTANCE hinstLib = LoadLibrary(TEXT("user32.dll"));
if (hinstLib != NULL) {
ShutdownBlockReasonCreate = (SBRCREATEFUNC) GetProcAddress(hinstLib,"ShutdownBlockReasonCreate");
if(ShutdownBlockReasonCreate != NULL) {
if(!(ShutdownBlockReasonCreate) (hWnd, L"Terminating Communication Sessions")) {
printf("\nfailed To Register Reason, failure code: %d\n", GetLastError());
} else {
printf("\nRegistered Reason\n");
}
} else {
printf("\nCouldn't load ShutdownBlockReasonCreate procedure\n");
}
} else {
printf("\nFailed to LoadLibrary(\"user32.dll\")\n");
}
}
int _tmain(int argc, _TCHAR* argv[]) {
RegisterShutdownBlockReason();
printf("Type to terminate program.\n");
getch();
return 0;
};
As a workaround, could you create a message-only window at startup and use ShutdownBlockReasonCreate on its window handle?
It doesn't make sense to pass the console window handle from a console program because the console window is owned by the CSRSS subsystem, not your console program. Furthermore, what if your console is run in full-screen text mode? Regardless of who owns what, now there's not even a window around your console!
Will it let you pass a NULL hWnd?
EDIT: Okay then, what if your console program creates its own hidden window and uses that?
Related
i want to send a click message on button of a window that it's caption is "Form1" and button's caption is "button1" here is my code:
i checked this handles by SPY++ seems correct..
#include "stdafx.h"
#include <windows.h>
#include <conio.h>
int main()
{
while(1)
{
HWND HWin, btn;
HWin = FindWindowExA(NULL,NULL,NULL,"Form1");
btn = FindWindowExA(HWin,0,NULL,"button1");
SendMessage(btn,BM_CLICK,0,0);
_getch();
}
}
this code worked well and every thing is good... but when "Form1" is set to hidden sendMessage seems not work! Why???
notice that FindWindowExA(...) still return same handle while "Form1" is hidden, and is equal with previous (when is shown)
setting hidden/show of "Form1" is done by this lines:
to shown:
ShowWindow(HWin,SW_SHOW);
to hidden:
ShowWindow(HWin,SW_HIDE);
i'm running on VS 2010
i want to know if sendMessage not work on hidden window is there other way to do that??
thanks All
I'm assuming you are judiciously checking to make sure that your FindWindow calls are not returning NULL when the window is hidden before executing the message passing code.
Assuming you are getting valid HWNDs returned from FindWindow, instead of BM_CLICK message sent to the button itself. Try sending a WM_COMMAND message to the parent window.
if (HWin && btn)
{
LONG ctrlId = GetWindowLong(btn, GWL_ID);
SendMessage(HWin, WM_COMMAND, MAKEWORD((WORD)ctrlId, BN_CLICKED), (LPARAM)btn);
}
If the application itself is in a state where it's not expecting click notifications while hidden, you risk some really weird behavior.
I would think this would work for a win32 app or dialog. Not sure about a .NET forms app.
I'm working on an application for taking screenshots on Windows, OSX and Linux in C++/Qt. Now I need to set global hotkeys, so the user can take screenshots when the application is running in the background. I tried with Qxt and UGlobalHotkey, which are both Qt libraries, but neither of them seemed to work.
I tried to implement it for OSX with Carbon (tutorial), but I need to call a class member function, which just doesn't work. Could someone provide me with an example? You can find my code here. The function i need to call is new_screenshot().
Or is there any other way to achieve something like this? I really need my application to take a screenshot from the background, otherwise it's pretty useless (yes, I should probably have implemented it at the very beginning to see if it even works). Would it maybe be better to have a separate client for every platform (Cocoa Swift for OSX, GTK for Linux, C# client for Windows)? I have often thought about this the past few days.
Do I understand correctly that you want to call new_screenshot from the hot key event handler? If so, InstallApplicationEventHandler lets you pass a pointer to user data in 4th argument. Pass a pointer to your MainWindow instance (based on code from the tutorial):
MainWindow *mainWindow = ... // get main window somehow
InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,mainWindow,NULL);
Then you can use it in the event handler.
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
//Do something once the key is pressed
static_cast<MainWindow*>(userData)->new_screenshot();
return noErr;
}
I did something in the past with MFC and WIN32 API....so it only works on Windows...but pressing ALT+F10 was able to hide/show a window...
void CWinHideDlg::OnButtonActive()
{
CString tmp;
GetDlgItemText(IDC_BUTTON_ACTIVE,tmp);
if(0 == strcmp(tmp.GetBuffer(tmp.GetLength()),"Activate"))
{
m_myAtom=GlobalAddAtom("MY_GLOBAL_HOT_HIDE_KEY");
int err=RegisterHotKey(this->GetSafeHwnd(),m_myAtom,MOD_ALT,VK_F10);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Stop");
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(TRUE);
SetDlgItemText(IDC_STATIC_INFO,"Set the mouse over the window \nand press ALT + F10 to hide it...");
}
else
{
UnregisterHotKey(this->GetSafeHwnd(),m_myAtom);
GlobalDeleteAtom(m_myAtom);
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(FALSE);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Activate");
}
}
Basically this code activates/deactivates the hot key ALT+F10, once it activates you can hide/unhide a running window on the system by setting the mouse pointer over the window and press ALT+F10...
This is from the WindowProc function:
if(message == WM_HOTKEY)
{
CString tmp;
POINT pc;
GetCursorPos(&pc);
if(GetAsyncKeyState(VK_F10))
{
HWND hwnd=::WindowFromPoint(pc);
if(hwnd)
{
tmp.Format("%08Xh",hwnd);
m_HideWins.InsertString(m_HideWins.GetCount(),tmp);
::ShowWindow(hwnd,SW_HIDE);
}
}
}
You can use the code to register your own HOT Key and use it to take a screenshot...
Hope it helps...
The following sample has reliably returned the name of the process that is associated with the active window, but does not work with the newer modern/universal apps because it returns the name of a helper process WWAHost.exe on Windows 8 and ApplicationFrameHost.exe on Windows 10 rather than the name of the app.
HWND active_window = GetForegroundWindow();
GetWindowThreadProcessId(active_window, &active_process_id);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, active_process_id);
GetProcessImageFileName(active_process, image_name, 512);
With Windows 10 the ApplicationFrameHost.exe is the process that creates the window handles and is what gets returned by GetWindowThreadProcessId(), is there another Win32 API that can be used to get the active process of universal app that is active?
Also tried using GetApplicationUserModelId() and GetPackageFullName() with no success as they return APPMODEL_ERROR_NO_APPLICATION and APPMODEL_ERROR_NO_PACKAGE respectively because the active_process handle is just the helper process and not the process of the active application.
Any other APIs to use to get the process name of a Modern/Universal application given the hwnd of the window, or otherwise figure out the process name of the universal app is active.
Thanks in advance!
Be sure to use the Spy++ utility when you want to reverse-engineer something like this. Included with Visual Studio, you need the 64-bit version in Common7\Tools\spyxx_amd64.exe. Use Search > Find Window and drag the bullseye to a UWP app, like Weather.
You'll see the window you'll find with GetForegroundWindow(), it has at least 3 child windows:
ApplicationFrameTitleBarWindow
ApplicationFrameInputSinkWindow
Windows.Core.UI.CoreWindow, that's the host window for the UWP app and the one you are interested in. Right-click it and select Properties, Process tab, click the Process ID. That takes you to the real owner process you want to know.
So you just need to make an extra step from the code you already have, you just have to enumerate the child windows and look for one with a different owner process. Some C code, trying to make it as universal as possible without making too many assumptions and not enough error checking:
#include <stdio.h>
#include <Windows.h>
typedef struct {
DWORD ownerpid;
DWORD childpid;
} windowinfo;
BOOL CALLBACK EnumChildWindowsCallback(HWND hWnd, LPARAM lp) {
windowinfo* info = (windowinfo*)lp;
DWORD pid = 0;
GetWindowThreadProcessId(hWnd, &pid);
if (pid != info->ownerpid) info->childpid = pid;
return TRUE;
}
int main()
{
Sleep(2000);
HWND active_window = GetForegroundWindow();
windowinfo info = { 0 };
GetWindowThreadProcessId(active_window, &info.ownerpid);
info.childpid = info.ownerpid;
EnumChildWindows(active_window, EnumChildWindowsCallback, (LPARAM)&info);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info.childpid);
WCHAR image_name[MAX_PATH] = { 0 };
DWORD bufsize = MAX_PATH;
QueryFullProcessImageName(active_process, 0, image_name, &bufsize);
wprintf(L"%s\n", image_name);
CloseHandle(active_process);
return 0;
}
Output on the Weather program:
C:\Program Files\WindowsApps\Microsoft.BingWeather_4.5.168.0_x86__8wekyb3d8bbwe\
Microsoft.Msn.Weather.exe
Here is a small console app application that continuously (so you can test it easily selecting different windows on your desktop) display information about the current foreground window process and store process, if any.
Apps can have a window hierarchy that can span multiple processes. What I do here is search the first sub window that has the 'Windows.UI.Core.CoreWindow' class name.
This app uses the UIAutomation API (and also smart pointers, smart BSTRs and smart VARIANTs provided by the #import directive). I suppose you can do the same with standard Windows SDK, but I find the UIAutomation used this way quite elegant.
#include "stdafx.h"
#import "UIAutomationCore.dll"
using namespace UIAutomationClient;
int main()
{
// initialize COM, needed for UIA
CoInitialize(NULL);
// initialize main UIA class
IUIAutomationPtr pUIA(__uuidof(CUIAutomation));
do
{
// get the Automation element for the foreground window
IUIAutomationElementPtr foregroundWindow = pUIA->ElementFromHandle(GetForegroundWindow());
wprintf(L"pid:%i\n", foregroundWindow->CurrentProcessId);
// prepare a [class name = 'Windows.UI.Core.CoreWindow'] condition
_variant_t prop = L"Windows.UI.Core.CoreWindow";
IUIAutomationConditionPtr condition = pUIA->CreatePropertyCondition(UIA_ClassNamePropertyId, prop);
// get the first element (window hopefully) that satisfies this condition
IUIAutomationElementPtr coreWindow = foregroundWindow->FindFirst(TreeScope::TreeScope_Children, condition);
if (coreWindow)
{
// get the process id property for that window
wprintf(L"store pid:%i\n", coreWindow->CurrentProcessId);
}
Sleep(1000);
} while (TRUE);
cleanup:
CoUninitialize();
return 0;
}
Does taking snapshot of running processes and pulling the name out of it by comparing process id not work?
Full reference here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686837(v=vs.85).aspx
But you fix the snapshot with CreateToolhelp32Snapshot().
Or from WTSEnumerateProcesses() and surrounding API?
Pretty sure it worked in Win 8. Is it broken in 10?
Starting from Win10 Anniversary Update ApplicationFrameHost child window return anything but UWP application. It worked only in Tablet mode after relogon.
Here is a sample from Allegro5 tutorial: (to see the original sample, follow the link, I've simplified it a bit for illustratory purposes.
#include <allegro5/allegro.h>
int main(int argc, char **argv)
{
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
al_init()
display = al_create_display(640, 480);
event_queue = al_create_event_queue();
al_register_event_source(event_queue, al_get_display_event_source(display));
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
while(1)
{
ALLEGRO_EVENT ev;
ALLEGRO_TIMEOUT timeout;
al_init_timeout(&timeout, 0.06);
bool get_event = al_wait_for_event_until(event_queue, &ev, &timeout);
//-->// if(get_event && ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
//-->// break;
//-->// }
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
}
al_destroy_display(display);
al_destroy_event_queue(event_queue);
return 0;
}
If I don't manually check for the ALLEGRO_EVENT_DISPLAY_CLOSE, then I can't close the window or terminate the program (without killing the process through task manager). I understand this. But in this case I don't understand how the minimize button works without me manually handling it. Can someone please explain?
Disclaimer: I don't know Allegro.
Minimizing a window at the most basic level only involves work from the process that deals with the windows (the Window Manager), not the process itself.
Terminating a program, usually requires files to be closed or memory to be freed or something else that only the process itself can do.
The biggest reason that you must handle it yourself via an event is that closing (destroying) a window invalidates the ALLEGRO_DISPLAY * pointer. The request to terminate the window comes from a different thread, so it would be unsafe to destroy it immediately. Allowing you to process it yourself on your own time is safe and easy, and fits in with the event model that Allegro 5 uses for all other things.
There are other ways to solve the problem, but they are no more simple than this method and don't really have any major advantages.
I don't know anything about allegro, but minimizing windows is generally handled by the window manager without the need of further intervention by your program. The main window is set to a "minimized"-state and your program continues running in the background without a visible window.
You can check if your app is being minized by intercepting specific window-messages (those being WM_ACTIVATEAPP, WM_ACTIVATE or WM_SIZE). Maybe allegro provides something like that, too.
In contrast closing the window does need to be done by your program. Clicking on the X simply sends a message to the window (WM_CLOSE), that the user has clicked it, and you have to respond accordingly (save states, quit the program, or you could prevent it).
At least that's how the normal winapi works, and allegro seems to work the same way.
I want to make the most simplest application that can communicate via windows send messages (and parse json). I have found a sample code:
CWnd* pWnd = FindWindow("old title");
pWnd->SendMessage(WM_SETTEXT,0,(LPARAM)"New title");
That works... but only if I use MS Visual Studios "create new MFC form application" wizard. How can I make a console application that sends messages to my program? Or can I? What do I need to include/link if I start an empty project or console application?
The goal in pseudocode:
a = ""
while !EOF
a += read(stdin)
commandArray = jsonToArray(a)
CWnd* pWnd = FindWindow("program");
pWnd->SendMessage(WM_COPYDATASTRUCT,0,commandArrayWrappedInCOPYDATASTRUCT);
exit
The annoyance is that the effective part of the code is roughly 20 lines (above), but the wizard generated part is hundreds of lines. And most of them is stuff that I don't understand. Plus, I get a window that I don't need.
EDIT
Final main.cpp (without the json stuff):
/*
This closes calculator
*/
#include <Windows.h>
#include <atlstr.h>
int main (void)
{
HWND HWnd = FindWindow(NULL, CStringW("Calculator"));
SendMessage(HWnd, WM_CLOSE, 0, 0);
return 0;
}
br,
Juha
If you want something so simple, then I'd just forget all about MFC and start with a basic console app from the New Project Wizard. MFC seems rather heavy duty for something so simple.