Using WM_Close in c# - c#

I am using the below code to exit a process programatically.
since i am new to this concept. I want to know how to use this below code.
Logic : I will have the process name to be terminated, i shud assign that to
this function.
Say if want to terminate a notepad, how to pass parameter [Process Name]
to this function ?
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0xF060;
public void CloseWindow(IntPtr hWindow)
{
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}

Use the Process.CloseMainWindow instead of manually sending the message. This will send the message to the main window of the process:
using System.Diagnostics;
// ...
foreach (var process in Process.GetProcessesByName("notepad.exe"))
process.CloseMainWindow();
Alternatively, you can use MainWindowHandle to get the handle of the main window of a Process and send a message to it:
foreach (var process in Process.GetProcessesByName("notepad.exe"))
CloseWindow(process.MainWindowHandle); // CloseWindow is defined by OP.
If you want to kill the process immediately instead of closing the main window, this is not a good approach. You should use the Process.Kill method instead.

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

Related

How to install hooks on a given window/process

I'm trying to install either a WH_KEYBOARD_LL or WH_MOUSE_LL hook into a certain Process/Window.
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookHandler fn, IntPtr module, uint dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
public bool Install(Process process)
{
const int WH_KEYBOARD_LL = 0x0D;
if (instance == IntPtr.Zero)
{
var threadId = GetWindowThreadProcessId(process.MainWindowHandle, IntPtr.Zero);
instance = SetWindowsHookEx(WH_KEYBOARD_LL, handler, IntPtr.Zero, threadId);
}
return instance != IntPtr.Zero;
}
Where handler is a reference to my IntPtr Callback(int nCode, IntPtr wParam, IntPtr lParam) callback.
I can successfully hook globaly by replacing the third SetWindowsHookEx argument to a result of the LoadLibrary("User32") call and making threadId 0, like so:
var module = LoadLibrary("User32");
SetWindowsHookEx(WH_KEYBOARD_LL, handler, module, 0u);
How do I get it to work?
You can't.
As documented, a WH_KEYBOARD_LL can be installed as a global hook only. Both low-level keyboard and mouse hooks are executed long before the eventual input receiver has been determined.
The diagram posted under When something gets added to a queue, it takes time for it to come out the front of the queue illustrates, when low-level hooks run.

Check if process is responding

I'm creating an application that needs to check the response of some process.
System.Diagnostics.Responding doesn't works properly. So I'm trying to find a solution using windows API.
I already tried SendMessageTimeOut like this:
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint msg,
UIntPtr wParam,
IntPtr lParam,
uint flags,
uint timeout,
out IntPtr pdwResult);
public static bool IsResponding(Process process)
{
IntPtr hProcess = IntPtr.Zero;
try
{
hProcess = OpenProcess(
ProcessAccessFlags.QueryInformation | ProcessAccessFlags.DuplicateHandle | ProcessAccessFlags.Synchronize,
false,
(uint)process.Id
);
if (hProcess == IntPtr.Zero)
return false;
IntPtr hResult = SendMessageTimeout(hProcess, 13, UIntPtr.Zero, IntPtr.Zero, SMTO_ABORTIFHUNG, 2000, out IntPtr pdwResult);
return hResult != IntPtr.Zero;
}
catch
{
return false;
}
finally
{
if (hProcess != IntPtr.Zero)
CloseHandle(hProcess);
}
}
Other attempt was with IsHungAppWindow.
[DllImport("user32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsHungAppWindow(IntPtr hwnd);
I really do not know why it always returns me that the application is not responding.
My PInvokes works fine, I think, don't throw anytime. And OpenProcess are working too.
I've create a WPF app that can respond and not respond every 15 sec. Task Manager can get No responding properly but my app no.
What I did wrong? All I read about advice me to use that two functions.
The problem is that SendMessageTimeout and IsHungAppWindow require you to pass window handles, but you are passing process handles. Obtain a handle to the application's main window, and pass that instead.

sending String from C# to MFC through SendMessage

I know how to PInvoke a method that wants a CString by using LPCTSTR instead and setting up the DllImport to call with the LPstr conversion.
However, how would I do it with SendMessage where LPARAM is an IntPtr?
Would this work?
[DllImport("user32.dll", CharSet = CharSet.Ansi)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam,
[MarshalAs(UnmanagedType.LPStr)] String lParam);
You can declare it simply like this:
[DllImport("user32.dll", SetLastError=true)]
static extern IntPtr SendMessage(
IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
The default marshalling is as an pointer to null-terminated character array. If you really want the ANSI version, then that's the default. And you should use SetLastError in case you want to capture the error code in case of failure.
I trust you know that it cannot work if the window is in a different process.

If a server is locked - is it posible to send keys to sub client window?

My program, finds any subwindows, the case if an 3-part app shows an Error box, then i want to close it.. and it works fine, when the server not is locked.
Code:
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool PostMessage(IntPtr hwnd, uint msg, IntPtr WParam, IntPtr lParam);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool BringWindowToTop(IntPtr hwnd);
public static bool FocusWindowAndSendEnter(IntPtr hWnd)
{
try
{ // hWnd = pointer to subwindow, like messagebox.
uint WM_KEYDOWN = 0x0100;
//Set focus
var res1 = BringWindowToTop(hWnd);
//Send enter_Key
var res2 = PostMessage(hWnd, WM_KEYDOWN, (IntPtr)Keys.Enter, IntPtr.Zero);
return (res1 == res2 == true);
}
catch (Exception ex)
{
Logger.LogException(MethodInfo.GetCurrentMethod().Name, ex);
}
return false;
}
Can this be done if the server is locked, but running?
When a computer is locked, you are very limited in what you can do - for security purposes. I doubt there is a way around this unless you either stop the computer being locked, or stop the message box from showing up in the first place.
You're attempting to solve a problem in the wrong methods.
Find out what you can about that error message box and do what you can to prevent that happening. Don't expect to have much you can do when the PC is locked.

Modifying keyboard-hook code to fit my own purposes... where to begin?

I'm writing a program that sits in the systray. It will have a keyboard hook into all typed input, in any open application. I want it to intercept any typed input, run code on that input, and then send the new 'correct' character to be typed. This new character will be what shows up in the app that has focus.
I found this code via another question on StackOverflow, and it looks good.
http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
I added it as a class in my solution, created a new instance of it in the Form1 constructor, and it compiles. Any typed input into any app shows up in the Visual Studio output pane, one character at a time.
The problem is that this code is way over my head. That's the drawback of using this great concise code for my keyboard hooks: I haven't had the trial and error to teach me how to use it.
I envisioned this program working something like this:
key is pressed, triggers an event
get key information from the event
do computation on the key information, pick the character to be typed
send that key to the relevant program
my character is typed rather than the original keypress character
How does this code fit in this chain of events? I need to read the input characters before they are inputed. Then, where would the code to analyse the input and decide the correct input live? Finally, what's the correct 'sendInput()' type command to invoke to send a character to whatever app has focus?
Here's the full code for reference:
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class InterceptKeys
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Thanks for any advice you have! Or, is there a better way to go about this?
Thanks!
UPDATE
My HookCallback method now looks like this:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
//Console.WriteLine((Keys)vkCode);
KBDLLHOOKSTRUCT replacementKey = new KBDLLHOOKSTRUCT();
Marshal.PtrToStructure(lParam, replacementKey);
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, true);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
Shoot... adding Marshal.StructureToPtr is close, but results in a A first chance exception of type 'System.ArgumentException' occurred in foobar.exe error.
VERSION WITH UNSAFE CODE, NO MARSHALLING, etc. (still doesn't output 'Z'!)
unsafe private static IntPtr HookCallback(int nCode, IntPtr wParam, void* lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
KBDLLHOOKSTRUCT* replacementKey = (KBDLLHOOKSTRUCT*)lParam;
replacementKey->vkCode = 90;
}
return CallNextHookEx(_hookID, nCode, wParam, (IntPtr) lParam);
}
At the moment, this code just writes to the console. This happens in line 4 of the HookCallback method. So you need to replace that line with your own code.
However, the info you're given isn't in a very C# friendly format. You need to look at the SDK docs for LowLevelKeyboardProc to figure out how to unpack it. It turns out all the good stuff is in lParam, which is a pointer to a KBDLLHOOKSTRUCT structure.
So your code needs to marshal that to a C# equivalent. You need to declare a KBDLLHOOKSTRUCT structure, or see if there's one on pinvoke.net, and use Marshal.PtrToStructure to unpack it. You can then party on this structure as much as Windows will allow -- I think modifying the event data is a better bet than trying to kill the keyboard event and then simulate a new one (for a start, I think the simulated "send keys" would run straight into the hook itself!) -- however I haven't tried this to see what it possible. The SDK struct does include a virtual key code and scan code, so you may be able to replace them to achieve the effect you want, but this will probably take some trial and error, and will be very specific to your app.
How does this code fit in this chain of events? I need to read the input characters before they are inputed. Then, where would the code to analyse the input and decide the correct input live?
The HookCallback method is the method which you're installing to intercept keystrokes.
Finally, what's the correct 'sendInput()' type command to invoke to send a character to whatever app has focus?
To modify the character which is passed to other processes, modify the parameters (nCode, wParam, and/or lParam) before you pass them to the CallNextHookEx method.

Categories

Resources