简体   繁体   English

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

[英]File search in Delphi is ignoring some Windows directories

I'm using this code from this thread ( How to Search a File through all the SubDirectories in Delphi ) to find files recursively: 我正在此线程( 如何通过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;

It's working but for some reason it's ignoring the directories Program Files, Program Files (x86) and Users. 它正在工作,但是由于某种原因,它忽略了目录Program Files,Program Files(x86)和Users。 Unfortunatelly, the files I'm searching are in those folders. 不幸的是,我正在搜索的文件位于这些文件夹中。 Does anybody know why it's happening? 有人知道为什么会这样吗?

Any tip will be very helpful, 任何提示都会非常有帮助,

Thanks 谢谢

Like Jerry Dodge mentioned, security rights is certainly one thing you might need to account for. 就像杰里·道奇(Jerry Dodge)提到的那样,担保权无疑是您可能需要考虑的一件事。 Your code may need to be run as an admin in order to access various system directories, and directories belonging to other users. 您的代码可能需要以管理员身份运行才能访问各种系统目录以及属于其他用户的目录。 For the most part, simply enumerating the directories you have mentioned does not require elevated rights. 在大多数情况下,仅枚举您提到的目录不需要提升的权限。 But if you find that you encounter directories that do, you can either: 但是,如果您发现遇到的目录,可以执行以下任一操作:

  1. add a UAC manifest to your app that requests elevation 将UAC清单添加到要求提升的应用程序中

  2. move your enumeration code into a separate process or COM object that you can then run elevated from an un-elevated process when needed. 将枚举代码移到单独的进程或COM对象中,然后可以在需要时从未提升的进程运行提升的代码。

But aside from that, the FindFilePattern() procedure you copied is also implemented wrong to begin with. 但是除此之外,您复制的FindFilePattern()过程一开始也是错误地实现的。 It is: 它是:

  1. comparing file attributes incorrectly. 错误地比较文件属性。 The expression (SR.Attr and faDirectory) = SR.Attr ) will be true if the entry is a file, or is a directory with NO ATTRIBUTES on it. 如果条目是文件或目录上没有属性 ,则表达式(SR.Attr and faDirectory) = SR.Attr )将为true。 It is not uncommon to encounter directories with attributes, such as system, compressed, indexed, etc. 遇到具有属性的目录(例如系统目录,压缩目录,索引目录等)并不少见。

  2. comparing file names incorrectly. 错误地比较文件名。 The expression (pos('.',SR.Name)=0) will be true for all files and directories that do not contain a . 对于不包含的所有文件和目录,表达式(pos('.',SR.Name)=0)将为true . character at all. 完全没有个性。 Almost all files have a . 几乎所有文件都有一个. , and even directories can have a . ,甚至目录也可以有一个. as well. 也一样 When handling directories, you need to ignore only the special . 处理目录时,您需要忽略special即可. and .. directory entries specifically, not any entry that has a . ..目录条目,而不是任何带有. in it. 在里面。

  3. Worse, the combination of #1 and #2 acting together is allowing directories that have attributes, and directories that contain . 更糟糕的是,#1和#2的共同作用是允许具有属性的目录和包含的目录. , to be treated as files instead of as directories. ,被视为文件而不是目录。 The code is not handling directories correctly in general, let alone recursively. 该代码通常无法正确处理目录,更不用说递归了。

  4. leaking all of the search handles. 泄漏所有搜索句柄。 FindClose() must be called if FindFirst() is successful, regardless of FindNext() . 无论FindNext()如何,如果FindFirst()成功,则必须调用FindClose() FindNext()

Try something more like this instead: 尝试类似这样的方法:

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;

Your application needs to be running with elevated privileges in order for it to access some subdirectories within the ones you speak of. 您的应用程序需要以提升的特权运行,才能访问您所说的子目录中的某些子目录。 As a temporary test, run "As Administrator" to verify this. 作为临时测试,运行“以管理员身份”进行验证。 If this is indeed your case, then you should add a manifest to require elevation upon startup. 如果确实如此,则应添加清单以在启动时要求提升。

Later versions of Delphi have this built-in. Delphi的更高版本具有此内置功能。 Under Project Options, go to the "Application" page, and check "Enable Administrator Privileges". 在“项目选项”下,转到“应用程序”页面,然后选中“启用管理员权限”。 Of course, this is the quick and easy way with the IDE, and you should instead consider writing your own custom manifest, especially if you're running an older version of Delphi which doesn't have this option. 当然,这是使用IDE的快速简便的方法,您应该考虑编写自己的自定义清单,尤其是在运行没有此选项的较旧版本的Delphi时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM