Как правильно закрыть процесс экранной клавиатуры из C# winform?

В настоящее время я разрабатываю средство просмотра изображений, которое позволяет пользователю вводить свой адрес электронной почты и получать изображения в цифровом виде. Меня беспокоит закрытие экранной клавиатуры. Я использую этот фрагмент кода для запуска процесса Windows:

string progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink";
string keyboardPath = Path.Combine(progFiles, "TabTip.exe");
Process keyboardProc = Process.Start(keyboardPath);

После чего я открываю VB InputBox, чтобы запросить адрес электронной почты (для чего я использую экранную клавиатуру, так как приложение будет отображаться на сенсорном экране). После этого приглашения я хочу автоматически закрыть процесс.

Я попытался закрыть процесс следующим образом:

keyboardProc.Kill();
keyboardProc.Dispose();
keyboardProc.Close();
keyboardProc = null;

Ни один из них не работает и просто выдает исключение:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.dll
Additional information: Cannot process request because the process has exited.

Я также пытался идентифицировать процесс по идентификатору и закрыть его таким образом, тоже не сработало. Я также просмотрел: C#/.NET: закрытие другого процесс за пределами главного окна, но он тоже не заработал.. :(

Я новичок в С#, и это первый раз, когда я вызываю процесс Windows из кода - я что-то упустил?

Заранее большое спасибо!


person Cassini    schedule 30.05.2013    source источник
comment
.Kill() у меня работает. Вы уверены, что убиваете его только один раз и больше ничего не делаете, что может вызвать исключение?   -  person pascalhein    schedule 30.05.2013
comment
Вы пробовали запускать приложение от имени администратора?   -  person Daniel    schedule 30.05.2013
comment
Нет ничего плохого в том, чтобы скрыть этот чернильный интерфейс, и не нужно ли его убивать?   -  person David    schedule 30.05.2013
comment
keyboardProc.CloseMainWindow() (MSDN) должен помочь.   -  person John Willemse    schedule 30.05.2013
comment
Спасибо за ваши комментарии, попробовал .Kill(), .CloseMainWindow() - оба выдают исключение, потому что процесс уже завершен: s Сейчас попробую скрыть   -  person Cassini    schedule 30.05.2013
comment
@csharpler Я не знаю, что может вызвать исключение. Все, что я делаю, это запускаю процесс, открываю InputBox и запрашиваю ввод, затем я хочу закрыть/убить процесс   -  person Cassini    schedule 30.05.2013
comment
Решил это, имитируя щелчок мышью с помощью виртуальной мыши ... схематично, но это сработало. Вот код   -  person Cassini    schedule 30.05.2013


Ответы (3)


ты можешь сделать:

            Process process = new Process();

            process.StartInfo.FileName = progFiles;//Filename
            process.Start();
            process.Close();
person praks    schedule 30.05.2013
comment
Пробовал :/ Спасибо за ответ! - person Cassini; 30.05.2013
comment
можешь добавить свой код? то, что вы упомянули выше в своем вопросе, должно работать, или вы делаете что-то другое - person praks; 30.05.2013
comment
Эй, да, я изменил свой код, чтобы решить эту проблему. Вы можете увидеть, что я сделал здесь: http://www.sourcepod.com/asczzd16-18920 - person Cassini; 30.05.2013

У меня тоже были проблемы с этим. По какой-то причине это работает, хотя и убивает все открытые процессы TabTip.

            //Kill all on screen keyboards
            Process[] oskProcessArray = Process.GetProcessesByName("TabTip");
            foreach (Process onscreenProcess in oskProcessArray)
            {
                onscreenProcess.Kill();
            }
person Panu Horsmalahti    schedule 31.07.2013

Следующий код откроет и закроет сенсорную клавиатуру в Window 10 быстрее, чем запуск/закрытие TabTip.exe напрямую. (проверено на маломощном планшете).

    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool PostMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    static extern IntPtr FindWindow(String sClassName, String sAppName);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, String lpszClass, String lpszWindow);

    /// <summary>
    /// Show the On Screen Keyboard
    /// </summary>
    #region ShowOSK
    public static void ShowOnScreenKeyboard()
    {
        IntPtr parent = FindWindow("Shell_TrayWnd", null);
        IntPtr child1 = FindWindowEx(parent, IntPtr.Zero, "TrayNotifyWnd", "");
        IntPtr keyboardWnd = FindWindowEx(child1, IntPtr.Zero, "TIPBand", "Touch keyboard");

        uint WM_LBUTTONDOWN = 0x0201;
        uint WM_LBUTTONUP = 0x0202;
        UIntPtr x = new UIntPtr(0x01);
        UIntPtr x1 = new UIntPtr(0x0);
        IntPtr y = new IntPtr(0x0100020);
        PostMessage(keyboardWnd, WM_LBUTTONDOWN, x, y);
        PostMessage(keyboardWnd, WM_LBUTTONUP, x1, y);
    }
    #endregion ShowOSK

    /// <summary>
    /// Hide the On Screen Keyboard
    /// </summary>
    #region HideOSK
    public static void HideOnScreenKeyboard()
    {
        uint WM_SYSCOMMAND = 0x0112;
        UIntPtr SC_CLOSE = new UIntPtr(0xF060);
        IntPtr y = new IntPtr(0);
        IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
        PostMessage(KeyboardWnd, WM_SYSCOMMAND, SC_CLOSE, y);
    }
    #endregion HideOSK
person M Safwan    schedule 09.01.2016
comment
У меня это работало частично. Он скрывает клавиатуру, но не показывает. - person Jordi Espada; 16.06.2020
comment
теперь это работает. Если нет или он больше не будет работать в будущем, проверьте новое имя с помощью Spy++ (VisualStudio›Tools›Spy++, поставляемый с пакетом C++). Имя класса — TIPBand, Caption — сенсорная клавиатура, а параметры x, x1 и y можно прочитать с помощью окна сообщений. - person M Safwan; 06.09.2020