I start the Windows On-Screen-Keyboard like that:
s_onScreenKeyboard = new Process();
s_onScreenKeyboard.StartInfo = new ProcessStartInfo("osk.exe");
s_onScreenKeyboard.EnableRaisingEvents = true;
s_onScreenKeyboard.Exited += new EventHandler(s_onScreenKeyboard_Exited);
s_onScreenKeyboard.Start();
This works fine, but when I try to stop it using the following code, it does not work, i.e. the OSK keeps running and the method returns false:
s_onScreenKeyboard.CloseMainWindow();
if (!s_onScreenKeyboard.HasExited)
{
if (!s_onScreenKeyboard.WaitForExit(1000))
{
s_onScreenKeyboard.Close();
//s_onScreenKeyboard.Kill();
}
}
When uncommenting s_onScreenKeyboard.Kill(); it is closed, but the problem is that osk.exe obviously uses another process called “msswchx.exe” which is not closed if I simply kill the OSK process. This way, I would end up with hundreds of these processes which is not what I want.
Another strange thing is that the CloseMainWindow() call worked at some time, but then it suddenly did not work anymore, and I do not remember what has changed.
Any ideas?
EDIT: I have found a solution myself. Please see my answer for details.
Background:
I am implementing an On-Screen-Keyboard for my application because it should work with a touchscreen. It is important that the keyboard layout matches the layout which is configured in Windows since the application will be shipped to many different countries. Therefore, instead of implementing a custom keyboard control with approx. 537 keyboard layouts (exaggerating a little here…), I wanted to utilize the Windows built-in On-Screen-Keyboard which adapts to the selected keyboard layout automatically, saving a lot of work for me.
I have found the/a solution myself:
When I successfully retrieve the
MainWindowHandleafter the process has been started, the call toCloseMainWindow()is also successful later on. I do not understand the reason for this, but the important thing is: it works!BTW, for others having the same problem: The
MainWindowHandleis not available immediately after starting the process. Obviously, it takes some milliseconds until the MainWindow is started which is why I use the following code to retrieve the handle:In this code I continuously get the
MainWindowHandleevery ~50ms as long as it is still equal toIntPtr.Zero. If the handle could not be retrieved after 2 seconds, I quit the loop to avoid an endless loop in case of error.