VBA调用osk.exe提示文件不存在无法启动是什么原因
故障原因
你碰到的是64位Windows系统的WOW64文件系统重定向机制导致的路径识别错误,和代码语法无关:
- 目前绝大多数VB6、32位Office VBA的运行环境都是32位进程,这类进程访问
C:\Windows\System32路径时,系统会自动把请求重定向到C:\Windows\SysWOW64目录,你代码里写的System32路径根本不会被实际访问。 - osk.exe(系统屏幕键盘)是64位原生程序,真实存储位置就是64位系统目录
C:\Windows\System32,32位进程默认无权限直接访问这个真实路径;而C:\Windows\SysWOW64目录本身就没有内置osk.exe,所以你写两个路径调用都会报文件不存在。 - 自定义的FileExists函数返回False也是同一个原因:传入System32路径时,函数实际检测的是SysWOW64目录下是否存在osk.exe,传入SysWOW64路径时检测的是本身就不存在的文件,自然返回False。资源管理器是64位进程,不受重定向规则限制,所以你能直接在System32目录下看到osk.exe文件。
解决方案
两种方案都可以直接生效,不需要修改系统文件:
方案1:通过特殊别名路径绕过重定向
32位进程可以通过系统预留的Sysnative特殊路径直接访问真实的64位System32目录,这个路径不会触发重定向规则,直接修改调用代码即可:
Shell "C:\Windows\Sysnative\osk.exe", vbNormalFocus
如果要做文件存在性校验,同样把检测路径替换为C:\Windows\Sysnative\osk.exe就能得到正确结果。
方案2:通过ShellExecute API直接调用系统程序
osk是系统注册过的内置可执行程序,不需要写全路径就能调用,也不会受重定向影响:
首先在模块顶部声明API函数:
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _ ByVal hWnd As Long, _ ByVal lpOperation As String, _ ByVal lpFile As String, _ ByVal lpParameters As String, _ ByVal lpDirectory As String, _ ByVal nShowCmd As Long) As Long
之后在需要启动屏幕键盘的位置写调用代码:
ShellExecute 0, "open", "osk.exe", vbNullString, vbNullString, vbNormalFocus
注意:不要尝试手动把System32下的osk.exe复制到SysWOW64目录,这种操作会破坏系统文件完整性,还会触发Windows系统文件保护机制自动还原文件,没有实际意义。
内容的提问来源于stack exchange,提问作者tmighty
相关产品推荐
相关产品推荐

