无法使用System.SYSUTILS.ForceDirectories创建文件夹
越来越多的用户抱怨说他们无法安装/启动我的应用程序。无法使用System.SYSUTILS.ForceDirectories创建文件夹
是什么问题:
使用System.SYSUTILS.ForceDirectories(...)
包括4个目录,不摆在首位存在的目录结构建造。这发生在应用程序第一次启动时。 在某些机器上,这似乎是不可能的,因为3210。
我知道究竟在何处发生错误(以下仅仅是一个代码片段):
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
我做了什么至今: 到目前为止,我无法重现确切的错误。我试图从用户那里获得所有权,但是显示出不同的错误。还要在该目录中设置特殊权限 - 拒绝“创建文件夹”等 - 都无济于事。
有什么我失踪或我可以在这些情况下做?
非常感谢帮助,非常感谢!
UPDATE1
现在,我得到了本地用户文件夹,这样做:
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;
UPDATE2
既然我已经使用SysErrorMessage(GetLastError函数),我知道了错误信息,这实际上表示没有错误。 我也知道(来自客户)第一个文件夹(创建的4个文件夹之外)被创建为隐藏文件夹,其他文件根本没有创建。不过,她可以使用上下文菜单创建文件夹。
UPDATE3
在UPDATE1提到的改变解决了错误。由于没有被存储在注册表中:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
程序试图直接写入到C:\ Program Files文件...(可执行文件的路径),其中一些用户没有权限来写。
我接受的Andre Ruebel的解决方案,但大家谁评论教我对此事的东西。感谢大家。
UPDATE4
要总括起来。问题确实是本地用户路径被提取的方式。在这个特定用户的情况下,注册表项没有价值。因此,数据被复制到安装目录下,该目录位于Program Files ...
长话短说:应用程序数据需要读/写访问权限,用户没有权限,因此发生错误。 再次感谢所有的答案,他们引导我走向正确的方向。
使用
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),只需滚动到代码片段的右边。 – rocksteady
我发现[this](http://stackoverflow.com/questions/12771473/finding-a-windows-users-true-application-data-folder)它很好地解释它 – rocksteady
不确定这是否相关,但是当打开该注册表项时右边第一个条目(标准)说:“!不要使用此注册表项”“使用SHGetFolderPath或SHGetKnownFolderPath函数” –
这不是如何找到特殊的文件夹位置。使用api函数。 –
谢谢,我总是乐于学习新的东西。你知道,这是最好的遗留代码,我更多的是一个蟒蛇人:) – rocksteady