简体   繁体   English

如何在delphi中获取当前用户的名称?

[英]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 看一下CSIDLSHGetFolderPath

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM