您好我在Windows 8中使用delphi FM2和XE3。
我遇到的问题是我希望用户按下按钮,然后导航到位于appdata ex中的子文件夹。 C:\ Users \用户Kobus \应用程序数据\ Roaming.minecraft
每个人都有一个不同的用户名,所以这不会起作用。
所以我使用这段代码来获取用户名:
function GetCurrentUserName : string;
const
cnMaxUserNameLen = 254;
var
sUserName : string;
dwUserNameLen : DWord;
begin
dwUserNameLen := cnMaxUserNameLen-1;
SetLength( sUserName, cnMaxUserNameLen );
GetUserName(PChar( sUserName ),dwUserNameLen );
SetLength( sUserName, dwUserNameLen );
Result := sUserName;
end;
username := GetCurrentUserName;
然后我说ShowMessage('C:\Users\'+username+'\AppData\Roaming\.minecraft\saves\');
检查输出。
我得到的输出是:'C:\ Users \ Kobus'由于某种原因导致路径名的其余部分丢失。
我需要显示的是:'C:\ Users \'Kobus'\ AppData \ Roaming.minecraft \ saves \'
感谢。
答案 0 :(得分:12)
问题是dwUserNameLen
包含字符串的长度,包括尾随零终止符。所以当你这样做时:
SetLength(sUserName, dwUserNameLen);
这导致sUserName
设置为'Kobus#0'
。在某些时候,您可以将其传递给Windows API对话框函数,该函数将字符串视为以null结尾的字符串,并在stray null-terminator处截断字符串。
所以你这样修理它:
SetLength(sUserName, dwUserNameLen-1);
请注意,如果调用失败,您还应检查GetUserName
的返回值:
if not GetUserName(PChar(sUserName), dwUserNameLen) then
RaiseLastOSError;
或一个相当保守的变体:
Win32Check(GetUserName(PChar(sUserName), dwUserNameLen));
最后一点。这是获取漫游应用程序数据文件夹的错误方法。首先,您要假设各种实现细节。在使用不同命名模式的旧版Windows上,您的方法将失败。或者是Windows的未来版本。或者以不同方式配置的当前版本。
执行此操作的正确方法是询问系统漫游应用程序数据文件夹的位置。使用CSIDL_APPDATA
(适用于较旧的Windows版本)或FOLDERID_RoamingAppData
(适用于现代Windows版本)执行此操作。
答案 1 :(得分:1)
我不需要花太长时间才能找到一个片段:)。 因此,在总结提示后,我在自己的应用程序中使用的内容变为:
//=================================================================
procedure TMainF1.UserTestClick(Sender: TObject);
const
cnMaxUserNameLen = 254;
var
sUserName : string;
dwUserNameLen : DWord;
begin
dwUserNameLen := cnMaxUserNameLen-1;
SetLength( sUserName, cnMaxUserNameLen );
Win32Check(GetUserName( PChar(sUserName), dwUserNameLen ));
sUserName := PChar( sUserName );
label_user.Caption := UpperCase(sUserName);
end;
//== works well with D7
答案 2 :(得分:0)
我认为您的问题是XY Problems
之一您想要阅读%AppData%\.minecraft\saves\
您在考虑如何阅读当前的Username
function GetShellFolder(CSIDLFolder : integer) : string;
begin
SetLength(Result, MAX_PATH);
SHGetSpecialFolderPath(0, PChar(Result), CSIDLFolder, false);
SetLength(Result, StrLen(PChar(Result)));
if (Result <> '') then
Result := IncludeTrailingBackslash(Result);
end;
....
//Usage
ShowMessage(GetShellFolder(CSIDL_APPDATA)+'.minecraft\saves');
<强>更新强>
替代
检查System.IOUtils
单元中的GetHomePath功能。
将为多平台做同样的结果。
uses System.IOUtils;
procedure TForm17.btn1Click(Sender: TObject);
begin
ShowMessage(TPath.GetHomePath() + TPath.DirectorySeparatorChar + '.minecraft\saves');
end;
答案 3 :(得分:-2)
username := GetEnvironmentVariable('username');
将username
设置为当前用户的名称,从而避免了复杂性。