【问题标题】:Can' t close OSK.exe under Windows 10在 Windows 10 下无法关闭 OSK.exe
【发布时间】:2017-07-10 14:57:39
【问题描述】:

我用下面的代码打开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 的问题?

【问题讨论】:

  • 这不是c语法,请去掉c标签
  • 不要使用Wow64DisableWow64FsRedirection() 在 Wow64 上运行 OSK。绕过system32 重定向的首选方法是到use the sysnative alias instead:“32 位应用程序可以通过将%windir%\Sysnative 替换为%windir%\System32 来访问本机系统目录。WOW64 将Sysnative 识别为用于表示文件系统不应该重定向访问。这种机制灵活且易于使用,因此,建议绕过文件系统重定向的机制。"
  • 如果你使用CreateProcess()而不是ShellExecute(),那么你可以在返回的进程句柄上使用TerminateProcess(),而不是使用窗口消息(由于UIPI,这无论如何都不起作用)。
  • 感谢您的建议。

标签: c++ winapi mfc win32gui


【解决方案1】:

如果你想查看 osk.exe 的清单,你可以在这里查看下一个 - uiAccess="true" 这是 User Interface Privilege Isolation (UIPI) ,也可以阅读类似的问题 UIAccess in 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'/>,或者以某种方式将您的应用程序作为提升权限运行

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-12
    • 1970-01-01
    • 2021-10-08
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    相关资源
    最近更新 更多