我一直在使用Lazarus 1.6.4和FPC 3.0.2编写一些代码来获取Windows中的USERNAME和Linux中的USER。为实现这一点,我使用了SysUtils.GetEnvironmentVariable函数。在Linux中,它工作得很完美,但在Windows中它会返回一些损坏的东西,看起来像UTF8字符串以错误的编码方式打开。我在Windows中的USERNAME具有西里尔符号,因此GetEnvironmentVariable不是实际名称,而是返回????????
,但它应该是Пользователь
。
这是我的代码:
function GetUserName: string;
{$IFDEF MSWINDOWS}
const
envVar = 'USERNAME';
{$ENDIF}
{$IFDEF UNIX}
envVar = 'USER';
{$ENDIF}
begin
Result := SysUtils.GetEnvironmentVariable(envVar);
{$IFDEF MSWINDOWS}
{ TODO : BUG: Does not work correct for non-latin strings }
Result := LazUTF8.UTF8ToWinCP(Result)
{$ENDIF}
end;
当它包含非latain符号时,它会返回损坏的字符串。
如何在Windows操作系统中以正确的编码GetEnvironmentVariable?
答案 0 :(得分:0)
在Windows上使用unicodestring重载3.0+ getenvironmentvariable中的Afaik,并使用-W变体。
var res,tag : unicodestring;
begin
tag:='HOME';
res:=getenvironmentvariable(tag);
end;
只是
getenvironmentstring (unicodestring('whatever'));
也可以,但请确保将utf8设置为默认编码,或将结果分配给unicodestring。
答案 1 :(得分:-1)
经过一天的运行后,我找到了适合我的解决方案。您应该使用SysUtils.GetEnvironmentVariable
的Unicode版本并将结果转换为Windows当前代码页。这里的代码如下:
uses
{$IFDEF MSWINDOWS}
LazUTF8
{$ENDIF}
;
function GetUserName: string;
const
envVar: UnicodeString =
{$IFDEF MSWINDOWS}
'USERNAME'
{$ENDIF}
{$IFDEF UNIX}
'USER'
{$ENDIF};
begin
// USE Unicode String Version only!
Result := SysUtils.GetEnvironmentVariable(envVar);
{$IFDEF MSWINDOWS}
Result := LazUTF8.UTF8ToWinCP(Result)
{$ENDIF}
end;
更新01.12.2017 我的解决方案取决于大卫在评论中提到的ENV。在讨论过程中,我找到了更可靠的解决方案here。以下代码:
function GetCurrentUserName: String;
{$IFDEF WINDOWS}
const
MaxLen = 256;
var
Len: DWORD;
WS: WideString;
Res: windows.BOOL;
{$ENDIF}
begin
Result := '';
{$IFDEF UNIX}
{$IF (DEFINED(LINUX)) OR (DEFINED(FREEBSD))}
Result := SysToUtf8(GetUserName(fpgetuid)); //GetUsername in unit Users, fpgetuid in unit BaseUnix
{$ELSE Linux/BSD}
Result := GetEnvironmentVariableUtf8('USER');
{$ENDIF UNIX}
{$ELSE}
{$IFDEF WINDOWS}
Len := MaxLen;
{$IFnDEF WINCE}
if Win32MajorVersion <= 4 then
begin
SetLength(Result,MaxLen);
Res := Windows.GetuserName(@Result[1], Len);
//writeln('GetUserNameA = ',Res);
if Res then
begin
SetLength(Result,Len-1);
Result := SysToUtf8(Result);
end
else SetLength(Result,0);
end
else
{$ENDIF NOT WINCE}
begin
SetLength(WS, MaxLen-1);
Res := Windows.GetUserNameW(@WS[1], Len);
//writeln('GetUserNameW = ',Res);
if Res then
begin
SetLength(WS, Len - 1);
Result := Utf16ToUtf8(WS);
end
else SetLength(Result,0);
end;
{$ENDIF WINDOWS}
{$ENDIF UNIX}
end;