1

I have an installation dialog (made with nsis) that has two buttons (install and cancel). I'm trying to write automated tests for the install process using low level win32 api. To click on the button(s) I use the following code:

char windowName[] = "Desktop Application Setup";
char cancelButtonText[] = "Cancel";

HWND hWndMainWindow = NULL;
HWND hButton = NULL;

hWndMainWindow = FindWindow(NULL, windowName);
if (hWndMainWindow)
{
    hButton = FindWindowEx(hWndMainWindow, NULL, NULL, cancelButtonText);
    if (hButton)
    {
        SendMessage(hButton, BM_CLICK, 0, 0);
    }
}

On Windows 7, this works perfectly. On Windows 10, it simply does nothing. It finds the button, it sends the message, but the click just doesn't happen.

Is this some security thing introduced in Windows 10? Is it a known issue?

conectionist
  • 2,694
  • 6
  • 28
  • 50
  • You are going about this the wrong way. Don't fake input. Improve your installer so that it can accept command line arguments and perform unattended or silent installation. – David Heffernan Oct 21 '15 at 10:10
  • I'm sorry. I realize now that my description is ambiguous. What I meant to say is that I'm trying to write automated tests for the install process (that simulate user clicks). I've edited the description. – conectionist Oct 21 '15 at 10:15
  • In that case use UI automation – David Heffernan Oct 21 '15 at 10:17
  • "If the button is in a dialog box and the dialog box is not active, the BM_CLICK message might fail." – Jonathan Potter Oct 21 '15 at 10:18
  • Do you consider C++ only solutions? How about Python? – Vasily Ryabov Oct 21 '15 at 10:19
  • 1
    @VasilyRyabov I'm actually using the pywinauto framework. I have a test that works fine on Windows 7 but fails on Windows 10 (as mentioned in the description). So I tried the win32 approach to see if it's a framework related issue or it's a Windows10 issue. And since it doesn't work with low level win32 api either I assume it's a Windows thing. – conectionist Oct 21 '15 at 10:25
  • @JonathanPotter It is active. It works on Windows 7 but not on Windows 10 under the same conditions. – conectionist Oct 21 '15 at 11:52
  • 3
    One trivial explanation is that the installer runs elevated, like all installers do, but your automation app does not. A non-elevated app cannot commandeer an elevated one, UAC was primarily invented to stop shatter attacks. Not otherwise different on Win7 btw. Next explanation is to heed the warning that the MSDN article for BM_CLICK mentions, you must call SetActiveWindow(). The kind of nasty little detail that an UI Automation library never gets wrong. – Hans Passant Oct 21 '15 at 12:33
  • 1
    @HansPassant Indeed, it was due to elevation. After running as administrator it worked. Thanks! – conectionist Oct 21 '15 at 13:08
  • I assumed you were running elevated since you claimed this was a difference between Windows 7 and Windows 10 – David Heffernan Oct 21 '15 at 13:32
  • 1
    @HansPassantL FYI, it was UIPI, not UAC, that prevents shatter attacks. A lower-privilege process cannot send UI messages to a higher-privilege process unless the higher-privilege process explicitly allows specific UI messages to pass through UIPI by calling `ChangeWindowMessageFilter/Ex()`. And this requirement has existed since Vista. – Remy Lebeau Oct 21 '15 at 20:32
  • get the button's ID (it is usually IDCANCEL for cancel button) and it's handle ( hWnd ) then `SendMessge(hDlg,WM_COMMAND,(WPARAM)MAKELONG(IDCANCEL,0),(LPARAM) hWndButton);` – milevyo Oct 23 '15 at 03:56
  • pay attention, Button'sText can contains "&" char that is invisible as in "&Cancel" to mark the shortkey – milevyo Oct 23 '15 at 03:59

1 Answers1

0

it is better to send WM_COMMAND with the ID of the button, but the way you are doing works also if Lang is always in English. but the problem with your case is that buttons on dialog usually have an "&" to indicate the keyboard short cut, and usually hidden by system unless you press alt key. (like menus).

so: text of the button is most likely to be "&cancel"

milevyo
  • 2,165
  • 1
  • 13
  • 18