4

こんにちは、私はWindows8でXE3と一緒にdelphiFM2を使用しています。

問題は、ユーザーがボタンを押してから、appdataexにあるサブフォルダーに移動することです。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 \'

ありがとう。

4

4 に答える 4

12

問題はdwUserNameLen、末尾のゼロターミネータを含む文字列の長さが含まれていることです。だからあなたがするとき:

SetLength(sUserName, dwUserNameLen);

これにより、sUserNameに設定され'Kobus#0'ます。次に、ある時点で、これをWindows APIダイアログ関数に渡します。この関数は、文字列をnullで終了する文字列として扱い、浮遊するnullターミネータで文字列を切り捨てます。

したがって、次のように修正します。

SetLength(sUserName, dwUserNameLen-1);

GetUserName呼び出しが失敗した場合の戻り値も確認する必要があることに注意してください。

if not GetUserName(PChar(sUserName), dwUserNameLen) then
  RaiseLastOSError;

またはかなり鮮明なバリアント:

Win32Check(GetUserName(PChar(sUserName), dwUserNameLen));

最後にもう1つ。これは、ローミングアプリのデータフォルダーを取得するための間違った方法です。まず、あらゆる種類の実装の詳細を想定しています。異なる命名パターンを使用する古いバージョンのWindowsでは、このアプローチは失敗します。または、Windowsの将来のバージョン。または、別の方法で構成された現在のバージョン。

これを行う正しい方法は、ローミングアプリのデータフォルダがどこにあるかをシステムに確認することです。CSIDL_APPDATA(古いWindowsバージョンの場合)または(最新のWindowsバージョンの場合)を使用してこれを行いFOLDERID_RoamingAppDataます。

于 2013-03-21T18:41:07.850 に答える
1

あなたの質問はXY 問題の 1 つだと思います

フルパスを読みたい実際の問題%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');

アップデート

ユニットのGetHomePath関数を確認してくださいSystem.IOUtils

マルチプラットフォームで必要なのと同じ結果が得られます。

uses System.IOUtils;

procedure TForm17.btn1Click(Sender: TObject);
begin
    ShowMessage(TPath.GetHomePath() + TPath.DirectorySeparatorChar + '.minecraft\saves');
end;
于 2016-01-04T00:40:38.040 に答える
-2
username := GetEnvironmentVariable('username');

現在のユーザーの名前に設定usernameし、複雑さを取り除きます。

于 2013-03-21T18:49:22.650 に答える