【问题标题】:Could not find system file when it actually exists实际存在时找不到系统文件
【发布时间】:2013-03-24 19:42:28
【问题描述】:

系统找不到alg.exe,但它确实存在 - “c:\windows\system32\alg.exe”。

我最近从 Win 7 x86 迁移到 x64,当我在 x86 上时,我对此没有任何问题,尝试了 Delphi 7 和 XE2。

我正在使用的代码:

if FileExists('c:\windows\system32\alg.exe') then
  ShowMessage('fe') else ShowMessage('fne');

试图以管理员权限获取文件的所有权 + 我的应用程序 - 同样的问题。

伙计们,检查 x64..

function IsWow64Process(Handle:THandle; var IsWow64 : BOOL) : BOOL; stdcall; external 'kernel32.dll';

function IS64 : Boolean;
var
 xIS64 : Bool;
begin
 if IsWow64Process(GetCurrentProcess, xIS64) then
  Result := xIS64 else RaiseLastOSError;
end;

【问题讨论】:

  • 作为一个轶事(以及一些需要钻石模组删除的东西),我可以告诉你,alg.exe 并不是我在System32 目录中最喜欢的文件。原因很简单:我习惯按 Win 键启动应用程序,输入应用程序名称的开头,然后按 Enter。现在,我最常使用的应用程序之一被命名为“AlgoSim”。我想你明白了。
  • 我的英语比我的钱包还差..里面只有~1美元..对不起
  • @user2200585 我的回答现在解决了您在编辑中提出的问题。
  • @Andreas Rejbrand - 你试过 Launchy 吗? (launchy.net) 与 Win7 中引入的按键启动功能类似,但更可控。还有一些不错的插件。
  • @HMcG:不,不喜欢不必要的第三方软件。我只需要记住输入“al”或“algo”!

标签: delphi


【解决方案1】:

这是因为WOW64 file system redirection,如果您的 32 位应用程序想要获得对本机 system32 目录的访问权限,则必须使用 Wow64DisableWow64FsRedirection 函数或 Sysnative 别名。

Wow64DisableWow64FsRedirection

试试这个示例

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows;

Function Wow64DisableWow64FsRedirection(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
  External 'Kernel32.dll' Name 'Wow64DisableWow64FsRedirection';
Function Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
  External 'Kernel32.dll' Name 'Wow64EnableWow64FsRedirection';

Var
  Wow64FsEnableRedirection: LongBool;
begin
 try
    if Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection) then
    begin
      if FileExists('c:\windows\system32\alg.exe') then
       Writeln('fe')
      else
       Writeln('fne');

      if not Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection) then
       RaiseLastOSError;
    end
    else
    RaiseLastOSError;
 except
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;

end.
end.

另外查看有关此主题的 MSDN 文档。

应用程序可以使用 WOW64 文件系统重定向器来控制 Wow64DisableWow64FsRedirection、Wow64EnableWow64FsRedirection 和 Wow64RevertWow64FsRedirection 函数。禁用文件系统 重定向会影响调用方执行的所有文件操作 线程,因此只有在需要单个线程时才应禁用它 CreateFile 调用并在函数后立即重新启用 返回。长时间禁用文件系统重定向可以 阻止 32 位应用程序加载系统 DLL,从而导致 申请失败。

系统原生

32 位应用程序可以通过以下方式访问本机系统目录 用 %windir%\Sysnative 替换 %windir%\System32。哇64 将 Sysnative 识别为用于指示文件的特殊别名 系统不应重定向访问。这种机制灵活且 易于使用,因此,建议使用绕过文件的机制 系统重定向。请注意,64 位应用程序不能使用 Sysnative 别名,因为它是虚拟目录而不是真实目录。

{$APPTYPE CONSOLE}

{$R *.res}

uses
  SysUtils,
  Windows;

begin
 try
    if FileExists('c:\windows\SysNative\alg.exe') then
     Writeln('fe')
    else
     Writeln('fne');
 except
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;

end.

【讨论】:

  • 我很高兴您编辑了答案以包含禁用 FS 重定向的警告。但是您的示例代码缺少重新启用重定向,并且还缺少错误检查。为了便于阅读,可以在示例中跳过它,但至少解释一下缺少的内容。
  • 我刚刚包含了对Wow64EnableWow64FsRedirection函数的调用。
  • 谢谢。我的建议是使用Win32Check()。节省了大量的样板文件。另外,也许我是偏执狂,但我会将FileExists 的结果读入Boolean,然后重新启用。然后才对 Boolean 中的值做出反应。
【解决方案2】:

您有一个在 64 位系统上运行的 32 位进程。您的进程在 WOW64 模拟器中运行,并受File System Redirector 的约束。这会将对 64 位系统文件夹 %windir%\System32 的引用重定向到 32 位系统文件夹 %windir%\SysWOW64。

在模拟器下运行的 32 位进程中访问 64 位系统文件夹的推荐方法是使用 %windir%\Sysnative 别名:

32 位应用程序可以通过将 %windir%\Sysnative 替换为 %windir%\System32 来访问本机系统目录。 WOW64 将 Sysnative 识别为用于指示文件系统不应重定向访问的特殊别名。这种机制灵活且易于使用,因此,建议使用绕过文件系统重定向的机制。请注意,64 位应用程序不能使用 Sysnative 别名,因为它是虚拟目录而不是真实目录。

当然,这个别名只存在于 64 位系统上。最简单的检查方法是测试TOSVersion.Architecture 的值。

虽然可以禁用重定向器,但不建议这样做。文档说:

应用程序可以使用 Wow64DisableWow64FsRedirection、Wow64EnableWow64FsRedirection 和 Wow64RevertWow64FsRedirection 函数来控制 WOW64 文件系统重定向器。禁用文件系统重定向会影响调用线程执行的所有文件操作,因此只有在需要单个 CreateFile 调用时才应禁用它,并在函数返回后立即重新启用它。长时间禁用文件系统重定向会阻止 32 位应用程序加载系统 DLL,从而导致应用程序失败。

我强烈建议您不要禁用文件系统重定向器。

【讨论】:

    猜你喜欢
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    相关资源
    最近更新 更多