Delphi 目录存在网络Map单元的函数奇怪行为

cczfrluj  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(156)

在 Delphi XE中,当我使用以下输入调用SysUtils DirectoryLists函数时,
Y:blabla
其中Y是网络Map单元,它正确地返回false,因为blabla不存在。
但当我调用以下输入时
'Y:\blabla\Y:\bla'
则返回true。
文档是穷人,我没有发现任何地方在互联网上的人有同样的问题
也许这里有人已经遇到了这个问题,或者知道发生了什么?

xuo3flqw

xuo3flqw1#

这似乎是DirectoryExists函数实现中的一个bug。
这是这个函数的相关代码

function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean;
{$IFDEF MSWINDOWS}
var
  Code: Cardinal;
  Handle: THandle;
  LastError: Cardinal;
begin
  Result := False;
  Code := GetFileAttributes(PChar(Directory));

  if Code <> INVALID_FILE_ATTRIBUTES then
  begin
    ...
    //more code
    ...
  end
  else
  begin
    LastError := GetLastError;
    Result := (LastError <> ERROR_FILE_NOT_FOUND) and
      (LastError <> ERROR_PATH_NOT_FOUND) and
      (LastError <> ERROR_INVALID_NAME) and
      (LastError <> ERROR_BAD_NETPATH);
  end;
end;
{$ENDIF MSWINDOWS}

字符串
正如您看到的,如果GetFileAttributes函数调用失败,GetLastError方法的结果将与一组可能的值进行比较。但是在您的情况下,传递无效路径将返回ERROR_BAD_PATHNAME(161)代码,因此函数返回True。

dzhpxtsq

dzhpxtsq2#

这个bug在XE 8中仍然存在(可能在其他版本中也存在)。正如上面RRUZ指出的那样,它存在于 BOTH DirectorySts()* 和 TDirectory. Sts() 的SysUtils实现中。
问题是,这一长串的“检查”,假设他们是 * 唯一有效的原因 *,INVALID_FILE_ATTRIBUTES可能已返回的上下文中的“存在”的文件夹。但我们调用这些例程的原因是 * 几乎总是 ,所以我们可以检查我们是否真的可以使用我们正在询问的文件夹。属性几乎总是意味着我们不能。无论哪种方式,目前正在进行的测试不会产生合理的结果。仅凭这一事实就使它成为一个完全多余的练习,因为它允许某些其他故障代码通过网络,并在不应该的时候将最终结果设置为TRUE。最初是这种疯狂的某种方法,沿着“哦,它存在,但可能是无效的”的路线,它福尔斯违反了固有的事实,即未来可能会带来更多的代码,这些代码是由许多未知的文件系统和/或硬件生成的:所以底线是,对于99.9%的使用率,得到 INVALID_FILE_ATTRIBUTES 应该意味着 * 文件夹不可用 ,因此,一旦已经建立,就允许返回TRUE是不合逻辑的。
不幸的是,我们无法知道是否有代码依赖于当前行为来识别“存在问题的现有路径”-在这种情况下,对当前存在的例程的调用必须首先进行路径语法验证检查:否则它会说用错误语法描述的路径“存在”,这是无稽之谈!之后不能再重复执行 GetLastError,因为错误已经被清除了。
因此,唯一的解决方法是使用代码 Package 任何 * Sysutils. DirectoryLists * 和(不幸的是)
TDirectory. Lists * 调用,以预先消除问题。例如:

DirectoryUsable(const Directory: string; FollowLink: Boolean = True): Boolean;
begin
   Result := GetFileAttributes(PChar(Directory)) <> INVALID_FILE_ATTRIBUTES;
   if Result then Result := DirectoryExists( Directory, FollowLink );
end;

字符串
要么这样,要么你做一个单独的前期验证所有的“坏”的情况下,你知道和恩巴卡德罗错过了-即发挥同样的失败游戏,因为他们做了。可怕的,但你去。
您也可以自己修改SysUtils库,添加缺少的案例,对于遇到的每一个新情况,你都必须在 Delphi * 和 * 的每一个版本中重新进行。如果Embarcadero最终“咬紧牙关”并找到一个更好的解决方案,那可能会更好。也许可以使用另一个默认的标志参数,即“拒绝所有无效目录”.我进一步建议这默认为TRUE。

lfapxunr

lfapxunr3#

Map到驱动器的路径(Y:)也有同样的问题。
完整路径\\IP\dir\dir的问题
所以现在我用的不是很好,但是工作功能:

function FolderExists(const BasePath: WideString): boolean;
const
  FIND_FIRST_EX_LARGE_FETCH          = $00000002;
  FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004;
var
  FindExHandle    : THandle;
  Win32FindData   : TWin32FindDataW;
  FindExInfoLevels: TFindexInfoLevels;
  FindExSearchOps : TFindexSearchOps;
  AdditionalFlags : DWORD;
  i, ii           : Integer;
  folderTime: TDateTime;
begin
  result := false;
  FindExInfoLevels := _FINDEX_INFO_LEVELS.FindExInfoBasic;
  FindExSearchOps  := _FINDEX_SEARCH_OPS.FindExSearchLimitToDirectories;
  AdditionalFlags  := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY;
  FindExHandle     := Winapi.Windows.FindFirstFileExW(PWideChar(IncludeTrailingBackslash(TDirectory.GetParent(ExcludeTrailingPathDelimiter(BasePath))) + '*.*' ), FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags);
  if (FindExHandle <> INVALID_HANDLE_VALUE) then
    repeat
      if ((Win32FindData.cFileName = ExtractFileName(ExcludeTrailingPathDelimiter(BasePath))) and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then begin
        result := true;
        break;
      end;
    until not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData);
  Winapi.Windows.FindClose(FindExHandle);
end;

字符串
函数可以很好地处理像\\IP\dir\dir这样的完整路径
是的,函数使用的不是最优算法:)(optimistic:ON)但它可以工作

相关问题