The code :
HWND hWnd; //this is a window handle of current process
/*
*here is executed in a dll in current process , and it will hang
*when hWnd is a window which is created by current process.
*/
WCHAR lpwWndName[1000];
GetWindowText(hWnd,lpwWndName,1000);
I had read the MSDN :
1,When hWnd is created by another process , GetWindowText will get the title from a special space;
2,When hWnd is created by current process ,GetWindowText will send a WM_GETTEXT to hWnd,this method may hang if the hWnd doesn't response WM_GETTEXT.
How to resove this issue ? Thank you .
The reason of this issue is excute GetWindowText() in the message process function.
message process function()
switch(code)
{
case WM_COMMAND:
GetWindowText(hWnd);
break;
case WM_GETTEXT:
break;
}
if hWnd is created by current process , GetWindowText() will send a WM_GETTEXT to the window , and wait for the result,but the WM_GETTEXT will be processed after process WM_COMMAND.And then it deadlocks.
Related
I want to start browser in minimized state, however in this list there's no option for minimizing. So I thought of using ShowWindow() but some issues arise. I don't know how to use EnumWindows() or its derivatives. Only alternative I know is GetWindow() but I'm not sure of the position of window at Z-order. This is my solution:
HWND hwnd,hwnd2; //hwnd is my application's top level window
char t[128];
std::string t2;
for(int i=0; i<128&&t2!="found"; i++)
{
if(!i||i==64) hwnd2=hwnd; //turn direction
hwnd2=GetWindow(hwnd2,i<64?2:3); //loop backwards and forwards
GetWindowText(hwnd2,t,GetWindowTextLength(hwnd2)+1);
t2=t; if(t2.find("New")!=-1) t2="Found"; //Default title is "New Tab..."
}
ShowWindow(hwnd2,SW_MINIMIZE);
Assuming there won't be more than 128 windows, it works fine but since a window takes ~2 seconds to open, at the time ShowWindow() occurs, the window is not yet ready. So I used a timer for it.
SetTimer(hwnd,1,2000,0);
and
case WM_TIMER:
KillTimer(hwnd,1);
ShowWindow(hwnd2,SW_MINIMIZE);
break;
But it's impossible to know the exact time so the window gets minimized after it's shown for some milliseconds. I tried setting multiple timers in an interval of 50ms.
for(int i=0; i<50; i++) SetTimer(hwnd,1+i,i*50,0);
and
case WM_TIMER:
KillTimer(hwnd,wParam);
ShowWindow(hwnd2,SW_MINIMIZE);
break;
It usually minimizes window before it's shown, not always though. Also it changes the cursor to busy state every 50ms. Is there a way to stop this when the minimizing successfully performed once? It's not possible to determine this from the return value of ShowWindow() so is there a way? How can minimizing window before it's shown be guaranteed? Can I somehow make it wait till browser window is ready then sending ShowWindow() on the right time at once? How can I improve my solution into an easier one?
WinExec gives you very little control over spawned process.
Use CreateProcess, and set LPSTARTUPINFOA lpStartupInfo's WORD wShowWindow; to SW_MINIMIZE
Make sure that dwFlags contains STARTF_USESHOWWINDOW
Here is how to use it:
#include <windows.h>
int main()
{
PROCESS_INFORMATION processInformation = { 0 };
STARTUPINFO startupInfo = { sizeof STARTUPINFO };
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_MINIMIZE;
wchar_t cmd[] = L"C:\\Program Files\\Internet Explorer\\iexplore.exe";
// Create the process
BOOL result = CreateProcess(NULL,
cmd, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
FALSE, // handles are not inherited
NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&startupInfo, // STARTUPINFO pointer
&processInformation); // receives PROCESS_INFORMATION
}
UPDATE
In the referenced doc, they state:
the wShowWindow member is used if the nCmdShow parameter of ShowWindow is set to SW_SHOWDEFAULT.
There is similar comment on the position and size field.
Apparently, some application do NOT use the defaults. For example, chrome and calc open their window at the position it was closed previously.
You can find that stored location in the Registry and update it.
More info
Google Chrome default opening position and size suggests to edit Preferences file. It looks like this:
"window_placement":{"bottom":1363,"left":406,"maximized":false,"right":1356,"top":217,"visible":false,"work_area_bottom":1400,"work_area_left":0,"work_area_right":2560,"work_area_top":0}
I've tried to invent keys like minimized, hidden, visible - no luck :)
You could shift the window off-screen; I have partial success - chrome moves it back in so at least a few pixels show...
I am building a program that would open Sublime text and after a period of time would close the application itself . I can't figure out how to close the application using the existing code .
This is what I have so far :
STARTUPINFO siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
if (CreateProcess(L"C:\\Program Files\\Sublime Text 2\\sublime_text.exe",
L" source.cpp",
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&siStartupInfo,
&piProcessInfo) == FALSE)
WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
::CloseHandle(piProcessInfo.hThread);
::CloseHandle(piProcessInfo.hProcess);
First, you are calling WaitForSingleObject() and CloseHandle() if CreateProcess() fails, which is useless. Don't call those functions unless it succeeds instead.
Second, you are calling the Unicode version of CreateProcess(), which has a caveat that your code is not handling. Per the CreateProcess() documentation:
lpCommandLine [in, out, optional]
The command line to be executed. The maximum length of this string is 32,768 characters, including the Unicode terminating null character. If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters.
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Third, if you want to terminate the process after a timeout, you could use TerminateProcess(), but that is brute force and should be avoided when possible. Sublime has a UI, so the preferred solution is to ask the UI to close itself down and then wait for it to do so, as documented on MSDN:
How To Terminate an Application "Cleanly" in Win32.
If you absolutely must shut down a process, follow these steps:
Post a WM_CLOSE to all Top-Level windows owned by the process that you want to shut down. Many Windows applications respond to this message by shutting down.
NOTE: A console application's response to WM_CLOSE depends on whether or not it has installed a control handler.
Use EnumWindows() to find the handles to your target windows. In your callback function, check to see if the windows' process ID matches the process you want to shut down. You can do this by calling GetWindowThreadProcessId(). Once you have established a match, use PostMessage() or SendMessageTimeout() to post the WM_CLOSE message to the window.
Use WaitForSingleObject() to wait for the handle of the process. Make sure you wait with a timeout value, because there are many situations in which the WM_CLOSE will not shut down the application. Remember to make the timeout long enough (either with WaitForSingleObject(), or with SendMessageTimeout()) so that a user can respond to any dialog boxes that were created in response to the WM_CLOSE message.
If the return value is WAIT_OBJECT_0, then the application closed itself down cleanly. If the return value is WAIT_TIMEOUT, then you must use TerminateProcess() to shutdown the application.
NOTE: If you are getting a return value from WaitForSingleObject() other then WAIT_OBJECT_0 or WAIT_TIMEOUT, use GetLastError() to determine the cause.
By following these steps, you give the application the best possible chance to shutdown cleanly (aside from IPC or user-intervention).
With that said, try something more like this:
BOOL CALLBACK SendWMCloseMsg(HWND hwnd, LPARAM lParam)
{
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId == lParam)
SendMessageTimeout(hwnd, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 30000, NULL);
return TRUE;
}
...
STARTUPINFO siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
WCHAR szFilename[] = L"C:\\full path to\\source.cpp";
if (CreateProcess(L"C:\\Program Files\\Sublime Text 2\\sublime_text.exe",
szFileName,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&siStartupInfo,
&piProcessInfo))
{
CloseHandle(piProcessInfo.hThread);
WaitForInputIdle(piProcessInfo.hProcess, INFINITE);
if (WaitForSingleObject(piProcessInfo.hProcess, SomeTimeoutHere) == WAIT_TIMEOUT)
{
EnumWindows(&SendWMCloseMsg, piProcessInfo.dwProcessId);
if (WaitForSingleObject(piProcessInfo.hProcess, AnotherTimeoutHere) == WAIT_TIMEOUT)
{
// application did not close in a timely manner, do something...
// in this example, just kill it. In a real world
// app, you should ask the user what to do...
TerminateProcess(piProcessInfo.hProcess, 0);
}
}
CloseHandle(piProcessInfo.hProcess);
}
This question already has answers here:
How and why does QuickEdit mode in Command Prompt freeze applications?
(2 answers)
Closed 6 years ago.
for an application of mine I have been playing around with the Windows API a bit, namely creating a very small wrapper for window functionality. Since I like to have console output as well, I created a console via AllocConsole(). I then noticed that highlighting text in this console (like if you want to copy something) 'freezes' the open window, ie. no messages will be processed, it is not click- or closable. Message loop and wndProc are both standard.
Two questions: is that intended/documented behaviour (I couldn't find anything about it) and if yes, is there a way to disable it? It's kind of annoying.
Thanks in advance
EDIT: as requested, the console creation code:
FILE *conOut = NULL;
FILE *conIn = NULL;
if (::AllocConsole())
{
::freopen_s(&conIn, "CONOUT$", "r", stdin);
::freopen_s(&conOut, "CONOUT$", "w", stdout);
// ...
if (conOut != NULL)
::fclose(conOut);
if (conIn != NULL)
::fclose(conIn);
::FreeConsole();
}
I created a test Win32 application with a basic Win32 project. I added a simple class to handle the console creation and tested two scenarios. What I found was the console window output will stop as if the thread generating the output is suspended when an Edit->Mark is done until the Mark is completed with a Copy or canceled.
The two scenarios tested with the Win32 application were: (1) printing to console window in a separate thread and (2) printing to console window in the main window message handling logic.
The particulars of the test program and details of the two scenarios tested are as follows.
Console.h
#pragma once
#include <stdio.h>
class CConsole
{
public:
CConsole(void);
~CConsole(void);
int Create(void);
public:
FILE *m_conOut;
FILE *m_conIn;
};
Console.cpp
#include "StdAfx.h"
#include "Console.h"
CConsole::CConsole(void)
{
}
CConsole::~CConsole(void)
{
}
int CConsole::Create(void)
{
if (::AllocConsole())
{
::freopen_s(&m_conIn, "CONIN$", "r", stdin);
::freopen_s(&m_conOut, "CONOUT$", "w", stdout);
}
return 0;
}
In the main file at the near the top where the Win32 project wizard put some global variables, I added an additional global variable CConsole myConsole; for my console and then I added a bit further down a simple function that is the target of a _beginthreadex(). The function looks like:
unsigned __stdcall myThread( void *x )
{
HWND hWnd = (HWND)x;
// allow for two different test scenarios depending on whether the
// SendMessage() is commented out or the fprintf() is commented out.
// if SendMessage() is live then the main window will write to the console window
// if fprintf() is live then this thread will write to the console window.
for (int i = 0; i < 50; i++) {
// SendMessage (hWnd, WM_USER, i, 0); // send a message to main window to request print
fprintf (myConsole.m_conOut, "This is line %d\n", i); // print from this thread
Sleep (1000);
}
return 0;
}
In the InitInstance(HINSTANCE hInstance, int nCmdShow) just before the return statement, I added the following two lines of code:
myConsole.Create();
_beginthreadex (NULL, 0, myThread, hWnd, 0, NULL);
Finally in the main message loop that handles the messages for the main window I added an additional message target:
case WM_USER:
fprintf (myConsole.m_conOut, "This is line %d\n", wParam);
break;
I then tried two different experiments by commenting out one of the two lines in my function that is the target of the _beginthreadex().
One was to print to the console window using fprintf() within that thread. The second test case was to send a message of WM_USER to the main window and ask it to use fprintf() to print to the console window.
What I found was that with the printing being done by the thread then I observed the following behavior when I used the Edit->Mark to begin the procedure of marking text to copy:
the main window was responsive to menu choices
the console window output stopped
when I cleared the mark or copied text, console window output resumed
The behavior was as if the thread writing to the console window was suspended until the Mark and Copy procedure was completed.
When the printing was done by the main window's message loop when handling the WM_USER message then I observed the following behavior when I used the Edit->Mark to begin the procedure of marking text to copy:
the main window was unresponsive to menu choices
the console window output stopped
when I cleared the mark or copied text, main window responsiveness returned as did console output
For some additional information about the Console Window Subsystem see Consoles. For a bit of information about the technology see WinEventProc Callback Function along with SetWinEventHook which describes this functionality to some extent as well as What Are WinEvents? and In-Context Hook Function Precautions.
See also Console Window Host in the book Windows Internals for a brief overview of the Console Window Subsystem.
And see Windows 7 / Windows Server 2008 R2: Console Host for an introduction to the architecture changes.
Finally The Console Host Process in Windows 7 from the book Inside Windows Debugging shows how to "discover the various layers involved in the printf sequence".
It may be possible to use the Console functions at a lower level to directly interface with the Console Window Subsystem in order to prevent the freezing of the thread which is doing I/O to the console window.
I want to use windows raw input to enable two mice input on one computer.
However, I failed to figure out how to get the WM_INPUT message. It seems to get the message, I need to do this:
MainWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
switch (nMsg)
{
...
case WM_INPUT:
{
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize,
sizeof(RAWINPUTHEADER));
.............
}
}
I think the OpenSceneGraph window should be a window's type,but how can I get the WM_INPUT message without using MainWndProc?
It seems I cannot get WM_INPUT message like this:
bool CallbackManager::handle(const GUIEventAdapter& ea, GUIActionAdapter& us)
{
if(ea.getEventType() == WM_INPUT)
Then should I get the windows handle and how to?
OpenSceneGraph is a cross plattform toolkit. The Windows messages are translated internally in OpenSceneGraph and turned into OSG specific types. What you get in the CallbackManager is completely detached from the Windows messages.
Short of diving into the OpenSceneGraph code and adding the multiple pointer device support in OSG's core, there's little you can do about it.
I try to get the name of executable name of all of my launched windows and my problem is that:
I use the method
UINT GetWindowModuleFileName(
HWND hwnd,
LPTSTR lpszFileName,
UINT cchFileNameMax);
And I don't understand why it doesn't work.
Data which I have about a window are: -HWND AND PROCESSID
The error is:
e.g:
HWND: 00170628
ProcessId: 2336
WindowTitle: C:\test.cpp - Notepad++
GetWindowModuleFileName(): C:\test.exe
HWND: 00172138
ProcessId: 2543
WindowTitle: Firefox
GetWindowModuleFileName(): C:\test.exe
HWND: 00120358
ProcessId: 2436
WindowTitle: Mozilla Thunderbird
GetWindowModuleFileName(): C:\test.exe
Note: test.exe is the name of my executable file, but it is not the fullpath of Notepad++... and it make this for Mozilla Thunderbird too... I don't understand why
I use the function like this:
char filenameBuffer[4000];
if (GetWindowModuleFileName(hWnd, filenameBuffer, 4000) > 0)
{
std::cout << "GetWindowModuleFileName(): " << filenameBuffer << std::endl;
}
Thank you for your response.
The GetWindowModuleFileName function works for windows in the current process only.
You have to do the following:
Retrieve the window's process with GetWindowThreadProcessId.
Open the process with PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights using OpenProcess.
Use GetModuleFileNameEx on the process handle.
If you really want to obtain the name of the module with which the window is registered (as opposed to the process executable), you can obtain the module handle with GetWindowLongPtr with GWLP_HINSTANCE. The module handle can then be passed to the aforementioned GetModuleFileNameEx.
Example:
TCHAR buffer[MAX_PATH] = {0};
DWORD dwProcId = 0;
GetWindowThreadProcessId(hWnd, &dwProcId);
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ , FALSE, dwProcId);
GetModuleFileName((HMODULE)hProc, buffer, MAX_PATH);
CloseHandle(hProc);
Aaah. I read the MSDN page at the bottom.
From http://support.microsoft.com/?id=228469 (archive.org link):
GetWindowModuleFileName and GetModuleFileName correctly retrieve information about windows and modules in the calling process. In Windows 95 and 98, they return information about windows and modules in other processes. However, in Windows NT 4.0 and Windows 2000, since module handles are no longer shared by all processes as they were on Windows 95 and 98, these APIs do not return information about windows and modules in other processes.
To get more information on Windows 2000, use the Process Status Helper set of APIs (known as PSAPI, see Psapi.h include file), available since Windows NT 4.0. APIs such as GetModuleFileNameEx and GetModuleBaseName offer equivalent functionality.
Try using GetModuleFileNameEx instead.
http://support.microsoft.com/?id=228469 (archive.org link)
The executive summary is, GetWindowModuleFileName() doesn't work for windows in other processes in NT-based Windows.
Instead, you can use QueryFullProcessImageName() once you have a handle to the process. You can get a handle to the process with OpenProcess(), which you can use once you have a process id. You can get the process id from the HWND by using GetWindowThreadProcessId()
This is an example of how get the name of executable that creates window, hope it can give you some ideas about:
while(true)
{
Sleep(250);//reduce cpu usage
CHAR __name[MAX_PATH];//name buffer
HWND hwnd;//window handle
DWORD pid;//process pid
hwnd=FindWindow(NULL,NULL);//find any window
PROCESSENTRY32 entry;//process structure containing info about processes
entry.dwSize=sizeof(PROCESSENTRY32);
HANDLE snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//get processes
if(hwnd!=0)
{
GetWindowThreadProcessId(hwnd,&pid);//get found window pid
}
if (Process32First(snapshot,&entry)==TRUE)//start listing processes
{
while (Process32Next(snapshot,&entry)==TRUE)
{
if (stricmp(entry.szExeFile,"explorer.exe")==0)
{
if(pid!=entry.th32ProcessID)//if found window pid is explorers one, skip it
{
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);//open processusing PROCESS_ALL_ACCESS to get handle
if(hProcess!=NULL)
{
GetModuleFileNameEx(hProcess,NULL,__name,MAX_PATH);//get executable path
cout<<"Found: "<<__name<<endl;
}
}
}
}
}
To use GetModuleFileNameEx() you probably will need to set linker settings to link library psapi. Also include psapi.h.