windows - 从 Delphi 启动 Windows Optimize 应用程序 (Windows 10)
问题描述
我们有一个旧版 Delphi 7 应用程序,它启动 Windows Defrag 和屏幕键盘应用程序,如下所示:
// Defragmentation application
ShellExecute(0, 'open', PChar('C:\Windows\System32\dfrg.msc'), nil, nil, SW_SHOWNORMAL);
// On-screen keyboard
ShellExecute(0, 'open', PChar('C:\Windows\System32\osk.exe'), nil, nil, SW_SHOWNORMAL);
两者都在 Windows XP 上工作,但在 Windows 10 上失败。我发现碎片整理应用程序的名称更改为dfrgui.exe
,但更新代码没有帮助。osk.exe
在 Windows 10 上仍会调用屏幕键盘。
这两个应用程序都可以手动/直接从命令行启动,或者在 Windows 资源管理器中双击它们。
我的怀疑是 Windows 安全性阻止我的应用程序从 启动任何东西,因为我可以从和从C:\Windows\System32
启动其他几个应用程序。Program Files
C:\Windows
任何人都可以帮忙吗?
解决方案
Delphi 7 只生成 32 位应用程序,没有生成 64 位应用程序的选项(在 XE2 中添加)。
%WINDIR%\System32
从在 64 位系统上运行的 32 位应用程序访问路径受 WOW64 的文件系统重定向器的约束,它将以静默方式将 64 位System32
文件夹的请求重定向到 32 位SysWOW64
文件夹。
您尝试运行的应用程序可能仅存在于 64 位System32
文件夹中,而不存在于 32 位SysWOW64
文件夹中。
为避免重定向,您需要:
替换为路径中
System32
的特殊别名(即),该别名仅在 WOW64 下运行时有效,因此您必须在运行时通过以下方式动态检测:Sysnative
'C:\Windows\Sysnative\osk.exe'
IsWow64Process()
function GetSystem32Folder: string; var Folder: array[0..MAX_PATH] of Char; IsWow64: BOOL; begin Result := ''; if IsWow64Process(GetCurrentProcess(), @IsWow64) and IsWow64 then begin SetString(Result, Folder, GetWindowsDirectory(Folder, Length(Folder))); if Result <> '' then Result := IncludeTrailingPathDelimiter(Result) + 'Sysnative' + PathDelim; end else begin SetString(Result, Folder, GetSystemDirectory(Folder, Length(Folder))); if Result <> '' then Result := IncludeTrailingPathDelimiter(Result); end; end; function RunDefrag: Boolean; var SysFolder: string; Res: Integer; begin SysFolder := GetSystem32Folder; Res := Integer(ShellExecute(0, nil, PChar(SysFolder + 'dfrgui.exe'), nil, nil, SW_SHOWNORMAL)); if Res = ERROR_FILE_NOT_FOUND then Res := Integer(ShellExecute(0, nil, PChar(SysFolder + 'dfrg.msc'), nil, nil, SW_SHOWNORMAL)); Result := (Res = 0); end; function RunOnScreenKeyboard: Boolean; begin Result := (ShellExecute(0, nil, PChar(GetSystem32Folder + 'osk.exe'), nil, nil, SW_SHOWNORMAL) = 0); end;
通过 暂时禁用重定向器
Wow64DisableWow64FsRedirection()
,然后在完成后通过重新启用它Wow64RevertWow64FsRedirection()
:function GetSystem32Folder: string var Folder: array[0..MAX_PATH] of Char; begin SetString(Result, Folder, GetSystemDirectory(Folder, Length(Folder))); if Result <> '' then Result := IncludeTrailingPathDelimiter(Result); end; function RunDefrag: Boolean; var SysFolder: string; OldState: Pointer; Res: Integer; begin Wow64DisableWow64FsRedirection(@OldState); try SysFolder := GetSystem32Folder; Res := Integer(ShellExecute(0, nil, PChar(SysFolder + 'dfrgui.exe'), nil, nil, SW_SHOWNORMAL)); if Res = ERROR_FILE_NOT_FOUND then Res := Integer(ShellExecute(0, nil, PChar(SysFolder + 'dfrg.msc'), nil, nil, SW_SHOWNORMAL)); Result := Res = 0; finally Wow64RevertWow64FsRedirection(OldState); end; end; function RunOnScreenKeyboard: Boolean; var OldState: Pointer; begin Wow64DisableWow64FsRedirection(@OldState); try Result := (ShellExecute(0, nil, PChar(GetSystem32Folder + 'osk.exe'), nil, nil, SW_SHOWNORMAL) = 0); finally Wow64RevertWow64FsRedirection(OldState); end; end;
更新osk.exe
:话虽如此,事实证明在启用 UAC 时不允许运行在 WOW64 下运行的 32 位进程:
Delphi - 屏幕键盘 (osk.exe) 在 Win32 上工作但在 Win64 上失败
因此,当应用程序在 WOW64 下运行时,您必须创建一个 64 位辅助进程以osk.exe
代表您的应用程序启动。
推荐阅读
- html - 如何ng隐藏一个div
- osgi - 在 Equinox 中运行 Xtext
- elasticsearch - Elasticsearch - Kubernetes [握手失败,集群名称不匹配]
- prestashop - 如何在 Prestashop 1.6 中以编程方式添加新客户组
- excel - VBA以特定格式将Excel单元格复制到Word
- c - 如何使用 scanf 函数从 ls -l 的结果中解析两个特定信息作为参数?
- javascript - 两步登录 - 第二步的问题
- angular - 我可以在不立即呈现更改的情况下更新 Firestore 文档吗?
- binary-tree - 重建一棵二叉树需要多少树旅行?
- javascript - 我想要输入的值,但它总是警告 0