using sendmessage to send wm_close to another process
Are you sure that the window you are finding is the correct one? You can check easily with Spy++. Moreover, when searching for a window, I think it's better to use EnumWindows. I'm not sure your method is correct.
Send WM_CLOSE message to a process with no window
Is there any way to send WM_CLOSE message?
WM_CLOSE
is sent to a window. If there is no window in the process, then there is nothing to process the message. If you wish to close a process that has no window, then sending WM_CLOSE
is not the solution.
It looks like you simply want to kill processes. And you are using WM_CLOSE
messages to trigger CTRL_CLOSE_EVENT
signals when the console processes have associated windows.
Since CTRL_CLOSE_EVENT
is already a rather brutal way to kill a process, you could be perfectly well justified, in my view, to simply kill it. You already have a Process
object. Simply kill it using Process.Kill()
.
On the other hand, perhaps the question that you really wanted to ask was:
How do I signal
CTRL_CLOSE_EVENT
in another process?
A related question can be found here: Can I send a ctrl-C (SIGINT) to an application on Windows? The best answer there in my view, not the accepted one, is that of Nemo1024. That answer links to his blog article: http://stanislavs.org/stopping-command-line-applications-programatically-with-ctrl-c-events-from-net/
As I understand it, that article should give you the information needed to solve your problem. It lists four scenarios. The first two involve WM_CLOSE
as a means to trigger the close signal. The third is to kill the process. And the fourth is probably what you are looking for. Of course this fourth option is the most complex. To quote from the article:
After finding a hint at the bottom of this thread, I finally bit the bullet and started the process without a window. When the time comes to stop a process, the parent attaches its console to the child, stops itself listening to Ctrl-C event and issues the event to the console, so that the attached child terminates. It then reinstates the Ctrl-C handler for itself and frees the console.
Using WM_Close in c#
Although I agree with Mehrdad's answer but if you really want to re-invent the wheel, then this is how to do it (This is without any error checking etc. Please add that yourself).
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
static bool CloseWindow(IntPtr hWnd)
{
SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
return true;
}
static void Main()
{
IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad");
bool ret = CloseWindow(hWnd);
}
BTW, Here is a good place to view Managed declarations of native API's
In win32 C++ programming to close a window, should I call DestroyWindow(hWnd) myself or SendMessage(WM_CLOSE, hWnd, 0, 0)?
You should PostMessage(hWnd, WM_CLOSE, 0, 0)
. It puts the WM_CLOSE
message into the window's message queue for processing, and the window can close properly as the message queue is cleared.
You should use PostMessage
instead of SendMessage
. The difference is that PostMessage
simply puts the message into the message queue and returns; SendMessage
waits for a response from the window, and you don't need to do that in the case of WM_CLOSE
.
Sending WM_CLOSE to C# application works unexpected
After playing with it whole day I have found the reason why this issue occurs. Custom action DLL is ok. The problem goes from .NET ListView control. If Visible property of the form is set to false in Shown event handler and if form have ListView control on it then it becomes immune to WM_CLOSE message sent from another application first time. WM_CLOSE just not appears in WndProc method. I have fixed it by overriding SetVisibleCore of the form but anyway this issue looks very strange and appers to be a bug in .NET.
How to use WM_Close in C#?
Provided you already have a handle to send to.
...Some Class...
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
//I'd double check this constant, just in case
static uint WM_CLOSE = 0x10;
public void CloseWindow(IntPtr hWindow)
{
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
...Continue Class...
Getting a handle can be tricky. Control descendant classes (WinForms, basically) have Handle's, and you can enumerate all top-level windows with EnumWindows (which requires more advanced p/invoke, though only slightly).
Related Topics
Appending Std::Vector to Itself, Undefined Behavior
How to Set Pointer to a Memory to Null Using Memset
Safety of Casting Between Pointers of Two Identical Classes
Converting Integer into Array of Digits
How Do C++ Progs Get Their Return Value, When a Return Is Not Specified in the Function
Knight's Tour Backtrack Implementation Choosing the Step Array
Checking If a Folder Exists (And Creating Folders) in Qt, C++
Is Lambdification of a Concept an Improvement or Bad Practice
Benefits and Portability of Boost Library
Boost C++ Regex - How to Get Multiple Matches
Error Redeclaring a for Loop Variable Within the Loop
Size of the Classes in Case of Virtual Inheritance
Changing R's Seed from Rcpp to Guarantee Reproducibility