Question

Here is my code for writing to the ini file.

 Ini := TIniFile.Create(ChangeFileExt('StudentALevelMathsTracker.exe','.ini')) ;
 try
   Ini.WriteString('Settings', 'FilePath', edtFilePath.text);
   Ini.UpdateFile;
 finally
   Ini.Free;
 end;

However when I run this I get an error saying

Project ALevelMathsTracker.exe raised exception class EIniFileException with message 'Unable to write to studentALevelMathsTracker.ini'

Is this a problem with the network I'm on or my code?

Was it helpful?

Solution

TIniFile is a thin wrapper around the PrivateProfile API.

If you do not specify a full path, the API creates the .ini file relative to the OS system folder, which you likely do not have write access to.

If you base the filename on Application.ExeName or ParamStr(0), you are creating the .ini file relative to your app's folder, which you likely do not have write access to, especially if the app is installed under Program Files.

What you should do is use SHGetFolderPath(CSIDL_APPDATA) or similar API to get the path to tbe user's AppData folder, create your own subfolder under it, and then create your .ini file in that subfolder.

OTHER TIPS

First, you should be making variables, so you yourself can read what is going on:

procedure TForm1.MyProc;
var
  Ini:TIniFile;
  FileName: string;
begin
  // probably can not write to this directory:
  //FileName :=  ChangeFileExt('StudentALevelMathsTracker.exe','.ini');
  FileName := 'c:\afolder_i_have_permission_to_write_to\StudentALevelMathsTracker.ini';

  Ini := TIniFile.Create(FileName) ;
 try
   Ini.WriteString('Settings', 'FilePath', edtFilePath.text);
   Ini.UpdateFile;
 finally
   Ini.Free;
 end;
end;

Once you have a variable named FileName, you can inspect it in the debugger, if the path where it is being written to can not be written to because it is not a location that the current user has write priveleges to, then the change above makes sense. However, since I suspect you are running inside the IDE, the problem may be something else.

Having the variable makes the value you pass into TIniFile easier to inspect and makes the logic you intended to write clearer to YOU, which makes the solution (the change to your code) more obvious to YOU.

I just ran into this problem, and found that WriteString internally calls WritePrivateProfileString and if the result is false then it raises the EIniFileException which effectively hide the true cause of the failure.

So you can wrap your code in a Try Except block and call RaiseLastOsError to show the error that windows was trying to alert you to.

This will help in tracking down the problem of such an error.

try
  Ini.WriteString('Settings', 'FilePath', edtFilePath.text);
  Ini.UpdateFile;
except
  on EIniFileException do
  begin
    // This will raise an EOSError Exception with a better message.
    RaiseLastOsError;
  end;
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top