【问题标题】:How to get the name of the current user in delphi?delphi如何获取当前用户的名字?
【发布时间】:2013-03-21 18:38:06
【问题描述】:

您好,我在 Windows 8 中使用带有 XE3 的 delphi FM2。

我遇到的问题是我希望用户按下按钮,然后导航到位于 appdata ex 中的子文件夹。 C:\Users\Kobus\AppData\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\'

谢谢。

【问题讨论】:

  • 在 Windows XP 系统上,您的意思是 C:\Documents and Settings\<username> 等。可能。即使您知道用户名,您也不​​知道路径是什么。使用SHGetSpecialFolderPath 函数。

标签: delphi firemonkey


【解决方案1】:

问题在于dwUserNameLen 包含字符串的长度,包括尾随的零终止符。所以当你这样做时:

SetLength(sUserName, dwUserNameLen);

这导致sUserName 被设置为'Kobus#0'。在某些时候,您将其传递给 Windows API 对话框函数,该函数将字符串视为以空值结尾的字符串,并在杂散的空值终止符处截断字符串。

所以你这样修复它:

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 表示“最后一点”部分,这是迄今为止答案中最重要的部分。
  • 感谢您的帮助,请尝试按照您在最后一点中所说的进行操作。
  • 我个人会在这里做SetLength( sUserName, StrLen(sUserName) );。甚至懒惰sUserName := PChar(sUserName);。由于此 Win32 APi 调用不返回由多个零分隔的多个字符串,因此可以忽略 dwUserNameLen
【解决方案2】:

我认为您的问题是XY Problems 之一

你的实际问题是要读取%AppData%\.minecraft\saves\的完整路径

而你正在思考如何阅读当前的Username

看看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');

更新

另类

检查System.IOUtils单元中的GetHomePath函数。

将为多平台执行您想要的相同结果。

uses System.IOUtils;

procedure TForm17.btn1Click(Sender: TObject);
begin
    ShowMessage(TPath.GetHomePath() + TPath.DirectorySeparatorChar + '.minecraft\saves');
end;

【讨论】:

    【解决方案3】:

    我不需要挖太久就能找到一个 sn-p :)。 所以我在自己的应用中使用的东西,在总结了提示之后,变成了:

    //=================================================================
    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
    

    【讨论】:

      【解决方案4】:
      username := GetEnvironmentVariable('username');
      

      username 设置为当前用户名,避免复杂性。

      【讨论】:

      • 只包含代码的答案通常是一个糟糕的答案。您应该尝试解释代码试图做什么,它如何解决问题,并回答所提出的问题。
      • 恕我直言,这个答案的最大问题是它未能解决 OP 方法中的主要问题。
      • 好吧,如果你愿意的话。我建议这是一个相当明显的问题。回答了“如何在 delphi 中获取当前用户的名称”的问题。最简单的方法 IMO。
      • 问题很简单,就是如何获取数据——您是否希望任何人搜索问题的答案以使用该方法实现操作?问题不是“我如何找到当前用户的 minecraft.exe”
      • 您还应该知道,不能保证环境会包含该变量。但 API 调用总是给出正确的答案。
      猜你喜欢
      • 2014-10-28
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多