[英]How to get the name of the current user in delphi?
Hi there i am using delphi FM2 with XE3 in windows 8. 嗨,我在Windows 8中使用带有XE3的delphi FM2。
The problem im having is that i want the user to press a button and then navigate to a subfolder located in appdata ex. 我遇到的问题是我希望用户按下按钮,然后导航到位于appdata ex中的子文件夹。 C:\\Users\\Kobus\\AppData\\Roaming.minecraft
C:\\ Users \\ Kobus \\ AppData \\ Roaming.minecraft
Everybody has a diferant username so this wont work. 每个人的用户名都不同,所以这行不通。
So i use this code to get the username: 所以我使用此代码来获取用户名:
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;
Then i say ShowMessage('C:\\Users\\'+username+'\\AppData\\Roaming\\.minecraft\\saves\\');
然后我说
ShowMessage('C:\\Users\\'+username+'\\AppData\\Roaming\\.minecraft\\saves\\');
to check the output. 检查输出。
And the output i get is : 'C:\\Users\\Kobus' for some reason the rest of the path name is lost. 由于某种原因,我得到的输出是:'C:\\ Users \\ Kobus',其余路径名丢失了。
What i need to be displayed is : 'C:\\Users\\'Kobus'\\AppData\\Roaming.minecraft\\saves\\' 我需要显示的是:'C:\\ Users \\'Kobus'\\ AppData \\ Roaming.minecraft \\ saves \\'
Thanks. 谢谢。
The problem is that dwUserNameLen
contains the length of the string, including the trailing zero terminator. 问题是
dwUserNameLen
包含字符串的长度,包括结尾的零终止符。 So when you do: 因此,当您这样做时:
SetLength(sUserName, dwUserNameLen);
this results in sUserName
being set to 'Kobus#0'
. 这导致
sUserName
设置为'Kobus#0'
。 At some point you then pass this to a Windows API dialog function that treats the string as a null-terminated string, and truncates the string at the stray null-terminator. 然后,在某个时候将其传递给Windows API对话框函数,该函数将字符串视为以null终止的字符串,并在杂散的null终止符处截断该字符串。
So you fix it like this: 因此,您可以这样修复它:
SetLength(sUserName, dwUserNameLen-1);
Note that you should also check the return value of GetUserName
in case that call fails: 请注意,如果调用失败,还应该检查
GetUserName
的返回值:
if not GetUserName(PChar(sUserName), dwUserNameLen) then
RaiseLastOSError;
or a rather crisper variant: 或更清晰的变体:
Win32Check(GetUserName(PChar(sUserName), dwUserNameLen));
One final point. 最后一点。 This is the wrong way to get hold of the roaming app data folder.
这是获取漫游应用程序数据文件夹的错误方法。 For a start you are assuming all sorts of implementation details.
首先,您假设各种实现细节。 Your approach will fail on older versions of Windows which use different naming patterns.
您的方法将在使用不同命名模式的Windows的较旧版本上失败。 Or some future version of Windows.
或某些将来的Windows版本。 Or the current versions that have been configured in a different way.
或以不同方式配置的当前版本。
The right way to do this is to ask the system where the roaming app data folder is. 正确的方法是询问系统漫游应用程序数据文件夹在哪里。 Do that using
CSIDL_APPDATA
(for older Windows versions), or FOLDERID_RoamingAppData
(for modern Windows versions). 使用
CSIDL_APPDATA
(对于较旧的Windows版本)或FOLDERID_RoamingAppData
(对于现代Windows版本)执行此操作。
I didn't need to dig too long to find a snippet :). 我不需要花太多时间就可以找到一个片段:)。 So what I use in my own app, after summarising the hints, becomes:
因此,在总结提示后,我在自己的应用程序中使用的内容变为:
//=================================================================
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
i Think your question is one of the XY Problems 我认为您的问题是XY问题之一
Your actual problem that you want to read the full path of %AppData%\\.minecraft\\saves\\
您想读取
%AppData%\\.minecraft\\saves\\
的完整路径的实际问题
And you thinking in how to read the current Username
您在思考如何读取当前
Username
Look at CSIDL and SHGetFolderPath 看一下CSIDL和SHGetFolderPath
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');
UPDATE 更新
Alternative 另类
Check the GetHomePath function in System.IOUtils
unit. 检查
System.IOUtils
单元中的GetHomePath函数。
Will do the same result that you want for multi platforms. 将为多平台实现与您期望的结果相同的结果。
uses System.IOUtils;
procedure TForm17.btn1Click(Sender: TObject);
begin
ShowMessage(TPath.GetHomePath() + TPath.DirectorySeparatorChar + '.minecraft\saves');
end;
username := GetEnvironmentVariable('username');
将username
设置为当前用户的名称,从而避免了复杂性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.