Delphi中的文件搜索忽略了一些Windows目录

时间:2016-08-30 00:50:53

标签: windows delphi winapi

我正在使用此线程(How to Search a File through all the SubDirectories in Delphi)中的代码来递归查找文件:

procedure FindFilePattern(root:String;pattern:String);
var
  SR:TSearchRec;
begin
  root:=IncludeTrailingPathDelimiter(root);
  if FindFirst(root+'*.*',faAnyFile,SR) = 0 then
  begin
      repeat
          Application.ProcessMessages;
          if ((SR.Attr and faDirectory) = SR.Attr ) and (pos('.',SR.Name)=0) then
             FindFilePattern(root+SR.Name,pattern)
          else
          begin
           if pos(pattern,SR.Name)>0 then Form1.ListBox1.Items.Add(Root+SR.Name);
          end;
      until FindNext(SR)<>0;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FindFilePattern('C:\','.exe');
end;

它正在工作,但由于某种原因,它忽略了目录Program Files,Program Files(x86)和Users。不幸的是,我正在搜索的文件位于这些文件夹中。有人知道为什么会这样吗?

任何提示都会非常有用,

由于

2 个答案:

答案 0 :(得分:5)

就像Jerry Dodge所说,安全权肯定是你可能需要考虑的一件事。您的代码可能需要以管理员身份运行才能访问各种系统目录和属于其他用户的目录。在大多数情况下,简单地枚举您提到的目录不需要提升权限。但是,如果您发现遇到了目录,您可以:

  1. 向您的应用添加请求提升的UAC清单

  2. 将您的枚举代码移动到一个单独的进程或COM对象中,然后可以在需要时从未提升的进程中提升。

  3. 但除此之外,您复制的FindFilePattern()过程也是错误的。它是:

    1. 错误地比较文件属性。如果条目是文件,则表达式(SR.Attr and faDirectory) = SR.Attr )将为true,或者表达式为 NO ATTRIBUTES 的目录。遇到具有属性的目录并不罕见,例如系统,压缩,索引等。

    2. 错误地比较文件名。对于不包含(pos('.',SR.Name)=0)字符的所有文件和目录,表达式.将为true。几乎所有文件都有.,甚至目录也可以有.。处理目录时,您需要特别忽略特殊...目录条目,而不是任何包含.的条目。

    3. 更糟糕的是,#1和#2共同作用的组合允许将具有属性的目录和包含.的目录视为文件而不是目录。代码通常不能正确处理目录,更不用说递归了。

    4. 泄漏所有搜索句柄。如果FindClose()成功,则必须调用FindFirst(),无论FindNext()如何。

    5. 尝试更像这样的东西:

      uses
        SysUtils, Masks;
      
      procedure FindFilePattern(root: String; pattern: String);
      var
        SR: TSearchRec;
      begin
        root := IncludeTrailingPathDelimiter(root);
        if FindFirst(root + '*.*', faAnyFile, SR) = 0 then
        try
          repeat
            Application.ProcessMessages;
            if (SR.Attr and faDirectory) <> 0 then
            begin
              if (SR.Name <> '.') and (Sr.Name <> '..') then
                FindFilePattern(root + SR.Name, pattern);
            end else
            begin
              if MatchesMask(SR.Name, pattern) then
                Form1.ListBox1.Items.Add(Root + SR.Name);
            end;
          until FindNext(SR) <> 0;
        finally
          FindClose(SR);
        end;
      end;
      
      procedure TForm1.Button1Click(Sender: TObject);
      begin
        FindFilePattern('C:\', '*.exe');
      end;
      

答案 1 :(得分:0)

您的应用程序需要以提升的权限运行才能访问您所说的子目录中的某些子目录。作为临时测试,运行&#34;作为管理员&#34;验证这一点。如果确实如此,那么您应该在启动时添加清单以要求提升。

Delphi的后续版本具有此内置功能。在项目选项下,转到&#34;应用程序&#34;页面,然后选中&#34;启用管理员权限&#34;。当然,这是使用IDE的快捷方式,您应该考虑编写自己的自定义清单,特别是如果您运行的旧版Delphi没有这个选项。