【问题标题】:Cannot create Folder using System.SYSUTILS.ForceDirectories无法使用 System.SYSUTILS.ForceDirectories 创建文件夹
【发布时间】:2016-10-07 09:00:06
【问题描述】:

越来越多的用户抱怨他们无法安装/启动我的应用程序。

有什么问题:

使用System.SYSUTILS.ForceDirectories(...) 会构建一个目录结构,该目录结构由4 个目录组成,这些目录原本不存在。这发生在应用程序第一次启动时。 在某些机器上这似乎是不可能的,因为ForceDirectories() returns False

我确切知道错误发生在哪里(以下只是一个代码sn-p):

if ( not TDirectory.Exists(self.TempInstallPath) ) then
begin
    if (System.SYSUTILS.ForceDirectories(self.TempInstallPath)) then
      begin
        uGlobalFiles.DeleteDirectoryContents(self.TempInstallPath, self.GetLoggingFunc());
        if ( not self.copyDatabase(source) ) then
          raise TCopyDatabase_Exception.Create('Database could not be copied to: ' + sLineBreak + self.TempInstallPath);
      end
      else
      begin
        raise TPathCouldNotBeCreated_Exception.Create('adding a new directory failed with error: ' + sLineBreak + SysErrorMessage(GetLastError)
                + sLineBreak
                + 'destination folder: ' + self.TempInstallPath
                + sLineBreak
                + 'local user folder:' + self.LocaluserPath
                + sLineBreak
                + 'session time stamp:' + self.TimeStamp);
      end;
end;

使用哪个路径:

出于充分的理由,我决定在用户​​的本地 AppData 文件夹中创建路径和信息。 我从注册表中获取值:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders

到目前为止我做了什么: 到目前为止,我无法重现确切的错误。我试图从用户那里取得所有权,但这显示了一个不同的错误。还在该目录中使用特殊权限 - 拒绝“创建文件夹”等 - 都无济于事。

在这些情况下我有什么遗漏或我可以做的吗?

非常感谢帮助,非常感谢!

更新1

现在我得到了本地用户文件夹:

function GetShellFolder(CSIDLFolder : integer) : string;
begin
SetLength(Result, MAX_PATH);
  SHGetSpecialFolderPath(0, PChar(Result), CSIDLFolder, false);  // (CSIDL_LOCAL_APPDATA -- FOLDERID_LocalAppData)
  SetLength(Result, StrLen(PChar(Result)));
  if (Result <> '') then
    Result  := IncludeTrailingBackslash(Result);
end;

更新2

由于我已经使用过 SysErrorMessage(GetLastError),所以我知道错误消息,字面意思是没有错误。 我也知道(从客户那里)第一个文件夹(在要创建的 4 个文件夹中)是作为隐藏文件夹创建的,其他文件夹根本没有创建。不过,她可以使用上下文菜单创建文件夹。

UPDATE3

UPDATE1 中提到的更改解决了错误。由于注册表中没有存储任何内容:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders

程序试图直接写入 C:\Program Files...(可执行文件的路径),其中一些用户没有写入权限。

我接受了Andre Ruebel 的解决方案,但是评论的每个人都在这件事上教会了我一些东西。谢谢大家。

UPDATE4

总结一下。问题确实是提取本地用户路径的方式。在这个特定用户的情况下,注册表项没有任何价值。因此,数据被复制到安装目录,位于 Program Files...

长话短说:应用程序数据需要用户没有特权的读/写访问权限,因此发生了错误。 再次感谢所有的答案,他们引导我走向正确的方向。

【问题讨论】:

  • 不确定这是否相关,但是当打开该注册表项时,下面的第一个条目(标准)说:“!不要使用此注册表项”“改用 SHGetFolderPath 或 SHGetKnownFolderPath 函数”
  • 这不是找到特殊文件夹位置的方法。使用api函数。
  • 所以做一些调试。你不需要自己复制它。您需要从可以重现它的计算机获取已记录的调试输出。您正在浪费时间试图猜测问题所在。永远不要那样做。在您了解问题之前,永远不要解决问题。否则你只会破坏其他东西。所以,做调试,获取信息,了解问题,然后尝试寻找解决方案。
  • 您应该真正考虑使用实际安装程序以避免此类问题。编写自己的安装程序,特别是对于更高版本的 Windows,是主要开销。例如,使用 Inno Setup。
  • 当然可以调试。照我说的做。将日志记录添加到您的程序中。获得诊断。这称为跟踪调试。现代开发人员认为调试意味着 IDE 的一项早已被遗忘的技能。

标签: windows delphi permissions delphi-10-seattle create-directory


【解决方案1】:

使用

var
  P: array [0 .. max_path] of Char;
begin
  SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, @P[0]);
end;

获取 Appdata 目录。 如果 forcedirectories 函数失败,请使用

SysErrorMessage(getlasterror)

获取有意义的错误消息。

【讨论】:

  • FWIW, SHGetFolferPath(0, CSIDL_APPDATA, 0, 0, P) 可能也可以。
  • 我已经做了 SysErrorMessage(getlasterror),只要在代码 sn-p 中向右滚动即可。
  • 我发现this 很好地解释了它
猜你喜欢
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多