Не удается закрыть OSK.exe под Windows 10

Я использую код ниже, чтобы открыть osk.exe

HINSTANCE Dlg::ExecuteOSK()
{
    typedef BOOL (WINAPI * LPFN_IsWow64Process)(HANDLE, PBOOL);
    typedef BOOL (WINAPI * LPFN_Wow64DisableWow64FsRedirection)(PVOID *);
    typedef BOOL (WINAPI * LPFN_Wow64RevertWow64FsRedirection)(PVOID);
    LPFN_IsWow64Process fnIsWow64Process = NULL;
    LPFN_Wow64DisableWow64FsRedirection fnWow64DisableWow64FsRedirection = NULL;
    LPFN_Wow64RevertWow64FsRedirection fnWow64RevertWow64FsRedirection = NULL;
    fnIsWow64Process = (LPFN_IsWow64Process) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
    fnWow64DisableWow64FsRedirection = (LPFN_Wow64DisableWow64FsRedirection) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "Wow64DisableWow64FsRedirection");
    fnWow64RevertWow64FsRedirection = (LPFN_Wow64RevertWow64FsRedirection) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "Wow64RevertWow64FsRedirection");
    BOOL bIsWow64 = FALSE;
    PVOID OldValue = NULL;
    HINSTANCE handle;
    if (NULL == fnIsWow64Process || NULL == fnWow64DisableWow64FsRedirection || NULL == fnWow64RevertWow64FsRedirection)
    {
        handle = ::ShellExecute(NULL, "open", "OSK", NULL, NULL, SW_SHOW);
    }
    else
    {
        fnIsWow64Process(GetCurrentProcess(), &bIsWow64);

        if (TRUE == bIsWow64)
        {
            fnWow64DisableWow64FsRedirection(&OldValue);
            handle = ::ShellExecute(NULL, "open", "OSK", NULL, NULL, SW_SHOW);
            fnWow64RevertWow64FsRedirection(OldValue);
        }
        else
        {
            handle = ::ShellExecute(NULL, "open", "OSK", NULL, NULL, SW_SHOW);
        }
    }
    return handle;
}

И затем я хочу закрыть osk.exe, когда пользователь нажимает ввод.

BOOL CALLBACK EnumWindowsProc(
  _In_ HWND   hwnd,
   _In_ LPARAM lParam)
{
    char name[256];
    GetClassName( hwnd, name, sizeof(name) );
    if(strcmp(name,"OSKMainClass") == 0)
        SendMessage(hwnd, WM_CLOSE  , NULL, NULL); //I have tried WM_DESTROY
    return TRUE;
}

BOOL Dlg::PreTranslateMessage(MSG* pMsg) 
{
    if (pMsg->message == WM_KEYDOWN)
    {       
        int nKey = (int)pMsg->wParam;       

        switch(nKey)            
        {
        case VK_RETURN:     
            EnumWindows(EnumWindowsProc, NULL);

        }
    }

    return CBitmapDialog::PreTranslateMessage(pMsg);
}

Однако эту часть кода нельзя использовать для успешного закрытия osk.exe.

Я попытался поймать другое окно, оно может быть успешно закрыто.

Это проблема в Windows 10?

1 ответ

Решение

Если вы хотите проявить osk.exe Вы можете посмотреть здесь дальше - uiAccess="true" это Изоляция привилегий пользовательского интерфейса (UIPI), также читайте о подобной проблеме UIAccess в Manifest Files.

так как osk.exe иметь uiAccess="true" в манифесте это есть Mandatory Label\High Mandatory Level в знак но ваше приложение, если работает под UAC не повышен, обычно есть Medium Mandatory Level, в результате:

Процесс с более низким уровнем привилегий не может:

  • Используйте SendMessage или PostMessage для окон приложений, работающих с более высокими правами. Эти API возвращают успех, но молча отбрасывают сообщение окна.

но если ваше приложение получит High Mandatory Level в токене - вы можете закрыть osk.exe по следующему коду:

if (HWND hwnd = FindWindow(L"OSKMainClass", 0))
{
    PostMessage(hwnd, WM_CLOSE, 0, 0);
}

так что вам нужно иметь <requestedExecutionLevel level='requireAdministrator' uiAccess='false'/> в манифесте или как-то запустить ваше приложение с повышенными правами

Другие вопросы по тегам