无法在 Windows 10 下关闭 OSK.exe
Can' t close OSK.exe under 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成功。
我试过抓另一个window,可以成功关闭
Windows10 有问题吗?
如果您想查看 osk.exe
的清单,您可以在此处查看下一个 - uiAccess="true"
这是 User Interface Privilege Isolation (UIPI) , also read about similar problem UIAccess in Manifest Files
因为 osk.exe
在清单中有 uiAccess="true"
它在令牌中有 Mandatory Label\High Mandatory Level
。但是你的应用程序,如果 运行ning 在 UAC 下没有提升,通常有 Medium Mandatory Level
。结果:
A lower-privilege process cannot:
- Use SendMessage or PostMessage to application windows running with higher rights. These APIs return success but silently drop the window
message.
但如果您的应用程序获得 High Mandatory Level
令牌 - 您可以通过下一个代码关闭 osk.exe
:
if (HWND hwnd = FindWindow(L"OSKMainClass", 0))
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
因此您需要 <requestedExecutionLevel level='requireAdministrator' uiAccess='false'/>
在清单中或以某种方式 运行 您的应用程序已提升
我用下面的代码打开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成功。
我试过抓另一个window,可以成功关闭
Windows10 有问题吗?
如果您想查看 osk.exe
的清单,您可以在此处查看下一个 - uiAccess="true"
这是 User Interface Privilege Isolation (UIPI) , also read about similar problem UIAccess in Manifest Files
因为 osk.exe
在清单中有 uiAccess="true"
它在令牌中有 Mandatory Label\High Mandatory Level
。但是你的应用程序,如果 运行ning 在 UAC 下没有提升,通常有 Medium Mandatory Level
。结果:
A lower-privilege process cannot:
- Use SendMessage or PostMessage to application windows running with higher rights. These APIs return success but silently drop the window message.
但如果您的应用程序获得 High Mandatory Level
令牌 - 您可以通过下一个代码关闭 osk.exe
:
if (HWND hwnd = FindWindow(L"OSKMainClass", 0))
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
因此您需要 <requestedExecutionLevel level='requireAdministrator' uiAccess='false'/>
在清单中或以某种方式 运行 您的应用程序已提升