10

ほとんどのWindowsアプリケーションと同様に、ユーザーの「ローカルアプリケーションデータ」フォルダにデータを読み書きするDelphi6アプリケーションがあります。以下のコードを使用して、そのフォルダーを判別します。これまで、そのコードはほとんどのユーザーに有効でした。ローカルアプリケーションデータが予期されたフォルダーにないユーザーに遭遇しました:

C:\Users\Bob\AppData\Roaming\

通常、ローカルアプリのデータフォルダーは次のように解決されます。

C:\Documents and Settings\Bob\Application Data\

このユーザーの特定の状況で奇妙なのは、通常HKEY_LOCAL_MACHINEにあるいくつかのレジストリキーが実際にはHKEY_CURRENT_USERにあることです。それらはWindows7で実行されています。

より良い言葉がないために、ユーザーの「真の」アプリケーションデータを取得して、この状況をより適切にナビゲートできるようにする方法はありますか?CSIDL_APPDATA、CSIDL_COMMON_APPDATA、およびCSIDL_LOCAL_APPDATAの特別なフォルダーからインテリジェントに選択することが問題である場合、そのためのロジックは何ですか?お分かりのように、ユーザーが実行しているWindowsのバージョンや特定のPC構成に関係なく、正しいアプリケーションデータフォルダーを根絶できる汎用機能を探しています。

答えがあるように見えるこのStackOverflowの投稿を見つけましたが、.NETライブラリの関数を使用しており、Delphi 6を使用しています。このソリューションが私の質問に答える場合、誰かがDelphiでそれを複製する簡単な方法を教えてもらえますか?

現在のユーザーの「アプリケーションデータ」フォルダのパスを取得するにはどうすればよいですか?

// Function to get the app data special folder.
function GetAppdataFolder: string;
begin
   Result := GetSpecialFolderLocation(CSIDL_APPDATA);
end;
4

3 に答える 3

8

リンク先の.netコードEnvironment.SpecialFolder.ApplicationDataは、とまったく同じCSIDL_APPDATAです。したがって、コードは、リンク先の.netコードとすでに同等です。そして、これらは両方ともと同じ場所を参照しFOLDERID_RoamingAppDataます。

のドキュメントをご覧くださいFOLDERID_RoamingAppData。それは言う:

デフォルトパス%APPDATA%(%USERPROFILE%\ AppData \ Roaming)
レガシーデフォルトパス%APPDATA%(%USERPROFILE%\ Application Data)

「デフォルトパス」は、Vista以降で表示されるパスです。「レガシーパス」は、XPで表示されるものです。

観察した動作の違いは、XPとVista/7/8の予想される違いにすぎません。

私のWindowsマシンでは、

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

に評価します

C:\Users\heff\AppData\Roaming

言い換えれば、あなたのコードはすでに正しいことをしているのです。変更する必要はまったくありません。を使い続けてGetSpecialFolderLocation(CSIDL_APPDATA)ください。


このユーザーの特定の状況で奇妙なのは、通常HKEY_LOCAL_MACHINEにあるいくつかのレジストリキーが実際にはHKEY_CURRENT_USERにあることです。

それは珍しいことではありません。多くの場合、アプリケーションはでデフォルト設定を構成し、アプリケーションを最初に実行するときにHKLMそれらをコピーします。HKCU問題の設定の詳細を知らなければ、質問のその側面についてコメントするのは難しいです。

于 2012-10-07T18:42:29.107 に答える
5

これ(ラッパー)を使用できます。ShlApiをuses句に追加する必要があります。CSIDL_APPDATA上記のサンプルと同じように渡します。CSIDL_さまざまな値のリストについては、こちらのMSDNページを参照してください。

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;

テキストが表示される以前のWindows(XP以下)をサポートしている場合は、SHGetFolderPath代わりに次を使用できます。

function GetFolderPath(Wnd: HWnd; CSIDLFolder: Integer): string;
begin
  SetLength(Result, MAX_PATH);
  Result := SHGetFolderPath(Wnd, CSIDLFolder, nil, 0, PChar(Result);
  SetLength(Result, StrLen(PChar(Result)));
end;

Vista以降のみをサポートしている場合は、SHGetKnownFolderPath代わりにを使用して、それを渡す必要がありKNOWNFOLDERIDます。

レジストリの問題に関しては、Windows Vistaおよび7は、管理者以外のユーザーが書き込むことができる場所についてはるかに制限されており、発生する場所の1つはHKLMおよびHKCRです。それらのハイブにあったアイテムの多くは、現在HKCUにあるか、そこにミラーリングされています。

于 2012-10-07T18:41:12.133 に答える
5

CSIDL_APPDATA、CSIDL_COMMON_APPDATA、およびCSIDL_LOCAL_APPDATAの特別なフォルダーからインテリジェントに選択することが問題である場合、そのためのロジックは何ですか?

はい、それはそれの問題です。コードはすでに期待どおりに機能しています。

CSIDL_APPDATAFOLDERID_RoamingAppData)は、複数のマシン上の呼び出し元のスレッドの現在のユーザーアカウント(偽装可能)にアクセスできるデータ用です(大量の「ローミング」データ)。

CSIDL_LOCAL_APPDATAFOLDERID_LocalAppData)は、ローカルマシン上でのみ呼び出し元のスレッドの現在のユーザーアカウントにアクセスできるデータ用です(厳密な「ローカル」データ)。

CSIDL_COMMON_APPDATAFOLDERID_ProgramData)は、ローカルマシン上のすべてのユーザーアカウントのみがアクセスできるデータ用です(「ローミング」データではありません)。

于 2012-10-08T22:21:12.553 に答える