2017-12-01 10 views
0

私はLazarus 1.6.4とFPC 3.0.2を使って、WindowsではUSERNAMEを、LinuxではUSERを取得するコードをいくつか書いています。これを達成するために、私はSysUtils.GetEnvironmentVariable関数を使用しました。 Linuxでは完璧に動作しますが、WindowsではUTF8文字列が間違ったエンコードで開かれたようなものが壊れてしまいます。 Windowsの私のUSERNAMEにはキリル記号があるので、GetEnvironmentVariableの代わりに????????が返されますが、Пользовательになるはずです。ここ 私のコード:FreePascal:非ラテンのWindowsで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を正しいエンコーディングにするにはどうすればよいですか?

答えて

-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;  

UPDATE 2017年1月12日 私の解決策は、ENVに依存します。議論の中で私はより信頼性の高い解決策を見つけましたhere。以下のコード:3.0+ getenvironmentvariableで

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; 
+0

これはWindowsでユーザー名を取得する方法ではなく、さらにWindowsでANSIエンコーディングを使用したくない場合です。 –

+0

@DavidHeffernan詳しく説明してください。何をお勧めしますか? –

+0

制限された文字セットしかエンコードできないため、ANSIエンコーディングを使用する必要はありません。また、現在のユーザー名を取得するには、そのサービスを提供するWin32 API関数を使用します。たとえば、 'GetUserName'です。多分LazarusやFPC RTLは既にそれをラップしていますが、わかりません。 –

0

私の知る限りでは、Windows上でUnicodeStringのオーバーロードされ、それは-Wバリアントを使用しています。

var res,tag : unicodestring; 

begin 
    tag:='HOME'; 
    res:=getenvironmentvariable(tag); 
end; 

だけ

getenvironmentstring (unicodestring('whatever')); 

も動作していますが、デフォルトのエンコーディングとしてUTF8を設定するのいずれかを確認してください、またはのUnicodeStringに結果を割り当てることができます。

関連する問題