2

私のアプリケーションは Delphi でビルドされており、Windows 7 64 ビット マシンを除く他のプラットフォームで完全に動作します。アプリケーションを閉じようとするたびに、「アプリケーション file.ini に書き込めません」というエラーが表示されます。

これが閉じるための私のコードです

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
      frmMain.close;
end;
4

2 に答える 2

10

Program Filesこのエラーは、通常、Vista 以降 (管理者またはパワー ユーザーとして実行していない場合は XP) で非管理者が許可されていない の下にあるアプリ独自のフォルダーに書き込もうとしたことが原因で発生します。

.INI ファイルの適切なフォルダーを取得するためのコードを次に示します。

uses
  Windows,
  ShlObj;   // For SHGetSpecialFolderPath

function GetFolderLocation(Handle: HWnd; Folder: Integer): string;
begin
  Result := '';
  SetLength(Result, MAX_PATH);
  if not SHGetSpecialFolderPath(Handle, PChar(Result), Folder, False) then
    RaiseLastOSError;
end;

アプリケーションでこれらを使用して非ローミング プロファイル フォルダーを取得し、その下に作成されたサブフォルダーをアプリのデータ用に使用します。の作成中に設定されますTDataModule:

procedure TAppData.Create(Sender.TObject);
begin
  // DataPath is a property of the datamodule, declared as a string
  // CSIDL_LOCAL_APPDATA is the local non-roaming profile folder.
  // CSIDL_APPDATA is for the local roaming profile folder, and is more typically used
  DataPath := GetFolderLocation(Application.Handle, CSIDL_LOCAL_APPDATA);
  DataPath := IncludeTrailingPathDelimiter(DataPath) + 'MyApp\';
end;

さまざまなまたは値の意​​味については、 MSDN のドキュメント ページを参照してください。値は似ていますが、Vista 以降でのみ使用でき、 SHGetKnownFolderIDList で使用されますCSIDL_FOLDERID_FOLDERID_

サポートされていないというMS の警告を無視したくない方のために、推奨されるusingSHGetSpecialFolderPathの代替バージョンを次に示します。GetFolderLocationSHGetFolderPath

uses
  ShlObj, SHFolder, ActiveX, Windows;

function GetFolderLocation(Handle: HWnd; Folder: Integer): string;
begin
  Result := '';
  SetLength(Result, MAX_PATH);
  if not Succeeded(SHGetFolderPath(Handle, Folder, 0, 0, PChar(Result))) then
      RaiseLastOSError();
end;

そして最後に、Vista 以降のみを使用している場合は、SHGetKnownFolderPath を使用した例を次に示します。これは、Delphi の XE 以前のバージョンでは使用できないことに注意してください (AFAIK-2009 または 2010 の可能性があります) 。KNOWNFOLDERIDを使用する必要があります。の代わりにCSIDL_FOLDERID_LocalAppData:

uses
  ShlObj, ActiveX, KnownFolders;

// Tested on XE2, VCL forms application, Win32 target, on Win7 64-bit Pro
function GetFolderLocation(const Folder: TGuid): string;
var
  Buf: PWideChar;
begin
  Result := '';
  if Succeeded(SHGetKnownFolderPath(Folder, 0, 0, Buf)) then
  begin
    Result := Buf;
    CoTaskMemFree(Buf);
  end
  else
    RaiseLastOSError();
end;
于 2012-06-27T13:12:34.187 に答える
5

プログラム ディレクトリに ini ファイルを書き込まないでください。過去には機能していましたが、決して良い習慣ではありませんでした。

%APPDATA%ユーザー固有のアプリケーション データに使用する必要があります。

アプリケーション データを保存するベスト プラクティスをお読みください。

于 2012-06-27T11:37:56.313 に答える