Using Sendmessage to Send Wm_Close to Another Process

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



Leave a reply



Submit