Osk.exe无法正常终止,仍在后台运行的技术问题
解决Osk.exe进程无法通过Kill()彻底终止的问题
问题根源
直接调用Process.Kill()强制终止Osk.exe时,会触发系统级进程保护逻辑——作为Windows内置的屏幕输入工具,Osk存在特殊的生命周期管理,强制杀进程可能导致系统后台残留子进程或触发自动重启;而手动关闭是通过正常窗口消息退出,不会触发这类问题。另外你硬编码的WinSxS路径会随系统更新变化,可能导致启动的不是预期的Osk进程,进一步加重终止失败的问题。
解决方案
- 优化Osk启动逻辑:避免硬编码路径,根据系统位数和当前进程位数处理文件系统重定向,启动正确版本的Osk。
- 优先正常退出:先模拟手动关闭的行为发送窗口关闭消息,仅在正常退出失败时再强制终止。
修改后的代码
启动代码(含路径处理)
Imports System.IO Imports System.Runtime.InteropServices Public Class YourFormName Private ProcessusClavier As Process Public Sub ClavierCommandExecute() Dim oskPath As String Dim wow64State As Integer = 0 If Environment.Is64BitOperatingSystem AndAlso Not Environment.Is64BitProcess Then ' 32位程序在64位系统中访问System32会被重定向到SysWOW64,需临时关闭重定向 NativeMethods.Wow64DisableWow64FsRedirection(wow64State) End If ' 构建正确的Osk路径 oskPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "system32", "osk.exe") If Environment.Is64BitOperatingSystem AndAlso Not Environment.Is64BitProcess Then ' 恢复文件系统重定向 NativeMethods.Wow64RevertWow64FsRedirection(wow64State) End If Me.ProcessusClavier = Process.Start(oskPath) End Sub ' 声明系统API用于处理文件系统重定向 Private Class NativeMethods <DllImport("kernel32.dll", SetLastError:=True)> Public Shared Function Wow64DisableWow64FsRedirection(ByRef OldValue As Integer) As Boolean End Function <DllImport("kernel32.dll", SetLastError:=True)> Public Shared Function Wow64RevertWow64FsRedirection(ByRef OldValue As Integer) As Boolean End Function End Class
关闭代码(优先正常退出)
Public Sub FermerCommandExecute() ' 先处理当前启动的Osk进程 If Me.ProcessusClavier IsNot Nothing AndAlso Not Me.ProcessusClavier.HasExited Then ' 发送关闭窗口请求,模拟手动关闭 If Me.ProcessusClavier.CloseMainWindow() Then ' 等待3秒让进程正常退出 Me.ProcessusClavier.WaitForExit(3000) End If ' 若仍未退出,再强制终止 If Not Me.ProcessusClavier.HasExited Then Me.ProcessusClavier.Kill() Me.ProcessusClavier.WaitForExit() End If Me.ProcessusClavier.Dispose() Me.ProcessusClavier = Nothing End If ' 兜底检查所有残留的Osk进程 For Each proc In Process.GetProcessesByName("osk") If proc.CloseMainWindow() Then proc.WaitForExit(3000) End If If Not proc.HasExited Then proc.Kill() proc.WaitForExit() End If proc.Dispose() Next Me.Close() End Sub End Class
关键说明
- 文件系统重定向处理:32位程序在64位系统中直接访问
C:\Windows\System32会被系统重定向到C:\Windows\SysWOW64,导致启动的是32位版本的Osk,关闭重定向才能启动正确的64位Osk。 - CloseMainWindow()的作用:该方法向进程的主窗口发送
WM_CLOSE消息,和手动点击关闭按钮的逻辑完全一致,能让Osk正常释放资源并退出,避免系统触发进程保护。 - WaitForExit()超时设置:给进程预留足够的正常退出时间,避免过早执行强制终止。
内容的提问来源于stack exchange,提问作者Magellus
相关产品推荐
相关产品推荐

