Jump to content
limelect

INI problem

Recommended Posts

Crazy but true.

I have a solution moved to  TMemIniFile but need your help to understand

var
 TIFFileini: TIniFile;

 

begin
  TIFFileini:=
TIniFile;.Create('ComPortServer.ini');
   if TIFFileini.SectionExists('Tst0') then
Label1.Caption:='yes'
else  Label1.Caption:='No';

 

INI file

[Tst0]
HardFlow=0

 

ANY IDEA WHY I GET NO ????????????
 D10.2.3 never had such a problem

 

Share this post


Link to post

Does it help when you add the complete path to the file instead only the file name?

  • Like 1

Share this post


Link to post

Doesn't TIniFile fall back to some extremely ancient Windows methods? I would have expected an encoding problem with your text file. Can you provide the original .ini file?

Share this post


Link to post

@Der schöne Günther 2 lines this is the INI

 

Crazy as it sounds I gave a full path I got yes

then I deleted the full path I got yes.

Well now I am buffeled 

Is it Delphi that gives me a beautiful day? 

 

What I think there might have been hidden characters although no reason for it

 

 
 

Edited by limelect

Share this post


Link to post
23 minutes ago, limelect said:

Is it Delphi that gives me a beautiful day? 

 

What I think there might have been hidden characters although no reason for it

 

..or just the current folder was not the one where the ini file is located.

Share this post


Link to post
16 minutes ago, limelect said:

@Der schöne Günther 2 lines this is the INI

 

Crazy as it sounds I gave a full path I got yes

then I deleted the full path I got yes.

Well now I am buffeled 

Is it Delphi that gives me a beautiful day? 

 

What I think there might have been hidden characters although no reason for it

 

 
 

If you don't use a full path the program will look for the file in whatever it considers to be the "current directory" at the moment. That can depend on many things, e.g. on how you start the program, and it can even change during the program run, e.g. by using a file dialog. If you do want to keep your sanity (and control of the situation) always use full pathes. A program should use a specific folder for its files, e.g. one created under TPath.GetDocumentsPath or TPath.GetHomePath.

Share this post


Link to post
25 minutes ago, limelect said:

then I deleted the full path I got yes.

I'd bet your program saved it at the end without the full path, so you just have copied the right one to the right place ?

 

  • Like 1

Share this post


Link to post

1. current folder is where execution is.

2 first I checked in the IDE

3 then I executed outside the ide (in the folder)

4 a few hours it was NO.

 

it seems something with Windows as this is the only explanation

since now it is OK.

Or Delphi compilation no other explanation.

 

 

  • Confused 1

Share this post


Link to post

Let's just clarify the point I am with Delphi since #1 and have never seen such a thing.

Share this post


Link to post

probably a windows thing..

check inside profiles like, Users\YourUserName\AppData\Local\VirtualStore\Program Files (x86)\

 

ive seen windows move things..

Share this post


Link to post

TIniFile uses deprecated Windows APIs that haven't been safe to use since 32 bit Windows was release nearly 30 years ago. 

 

So yeah use TMemIniFile which has a native Delphi INI parser that won't cause you such trouble. 

 

Never ever use TIniFile is the rule here. 

Share this post


Link to post
3 hours ago, PeterBelow said:

If you don't use a full path the program will look for the file in whatever it considers to be the "current directory" at the moment.

That is actually incorrect in the case of TIniFile.  Internally, it uses the Win32 PrivateProfile API, and if you don't specify a full path then it will use the Windows folder, not the calling process' working directory:

Quote

If the lpFileName parameter does not contain a full path and file name for the file, WritePrivateProfileString searches the Windows directory for the file. If the file does not exist, this function creates the file in the Windows directory.

 

If lpFileName contains a full path and file name and the file does not exist, WritePrivateProfileString creates the file. The specified directory must already exist.

This is not the case with TMemIniFile.

Quote

If you do want to keep your sanity (and control of the situation) always use full pathes.

Agreed.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

There are lots of other good suggestions here but I'll just add one thing to check. By default, Delphi projects set their Output directory to .\$(Platform)\$(Config) meaning that while your project (and possibly your .INI file) are in a folder like \MyProject, the .EXE would be in \MyProject\Win32\Debug (for a Win32 app compiled with the Debug configuration). When it runs, it's running from \MyProject\Win32\Debug and therefore doesn't see the .INI file two folders up. When you specified the full path, it likely saved it (as @Attila Kovacspointed out) so that next time it ran, it found the second copy of the .INI file.

 

This has caught me a few times and now I always check the project's Output directory setting. The possible reason you haven't seen this before is either you had set the Output directory (and forgot about it) or you were using a much earlier version of Delphi (before multiple platforms) that left .EXEs in the same folder as the project.

Share this post


Link to post
1 minute ago, Remy Lebeau said:

if you don't specify a full path then it will use the Windows folder, not the calling process' working directory

Oh, that's right--I forgot about that! I often prepend the filename with the application's path in which case the above scenario I described happens.

Share this post


Link to post

Another trick is to use ExtractFilePath(paramstr(0)) to get the executable location.  It really depends on your use case and how the executable is deployed. 

 

using your example above, this would be:

   TIFFileini:= TIniFile.Create(ExtractFilePath(paramstr(0))+'ComPortServer.ini');

Share this post


Link to post
On 3/18/2022 at 6:36 PM, Steven Kamradt said:

Another trick is to use ExtractFilePath(paramstr(0)) to get the executable location.  It really depends on your use case and how the executable is deployed.

It is really not a good idea to store your data files in your program's installation folder, especially if it is installed under ProgramFiles.  Windows has dedicated folders set aside for storing data files, you should create your own subfolder underneath them, such as %APPDATA%\MyApp, etc.

Share this post


Link to post
1 hour ago, Remy Lebeau said:

It is really not a good idea to store your data files in your program's installation folder, especially if it is installed under ProgramFiles.

That depends. Our internal programs all do that. They aren't installed under program files, though.

  • Like 3

Share this post


Link to post
14 hours ago, Remy Lebeau said:

It is really not a good idea to store your data files in your program's installation folder, especially if it is installed under ProgramFiles.  Windows has dedicated folders set aside for storing data files, you should create your own subfolder underneath them, such as %APPDATA%\MyApp, etc.

Classic holy war "self-contained bundle aka portable vs scattered installation according to OS rules". I prefer the first. Ideally both options should be available to have to choose from

Share this post


Link to post
51 minutes ago, Fr0sT.Brutal said:

Classic holy war "self-contained bundle aka portable vs scattered installation according to OS rules". I prefer the first. Ideally both options should be available to have to choose from

That's why the mentioned internal programs support redirection with a section like this:

[redirect]
inifile=some\path\to\another\inifile

(and usually nothing else)

This will redirect the access to the inifile to a different file. It supports environment variables in the file name and the name can be relative to the main ini file.

It gets even more flexible by allowing to redirect sections or even single entries.

 

I'm using something similar in dzPrepBuild to keep version information in sync between several executables belonging to the same project, e.g. GExperts:

[Version Info]
AutoIncBuild=0
Build=redirect:..\..\SVN_Version.ini,SVN,HighestVersion
MajorVer=redirect:..\GExperts_version.ini,Version Info,MajorVer
MinorVer=redirect:..\GExperts_version.ini,Version Info,MinorVer
Release=redirect:..\GExperts_version.ini,Version Info,Release

[Version Info Keys]
FileVersion=1.3.4.0
FileDescription=GExperts for Delphi 2007
OriginalFilename={ProjectName}.dll
InternalName=GExperts for Delphi 2007
Comments=redirect:..\GExperts_version.ini,Version Info Keys,Comments
CompanyName=redirect:..\GExperts_version.ini,Version Info Keys,CompanyName
LegalCopyright=redirect:..\GExperts_version.ini,Version Info Keys,LegalCopyright
LegalTrademarks=redirect:..\GExperts_version.ini,Version Info Keys,LegalTrademarks
ProductName=redirect:..\GExperts_version.ini,Version Info Keys,ProductName
ProductVersion=redirect:..\GExperts_version.ini,Version Info Keys,ProductVersion

Of course if is that is done excessively you will end up with an unmaintainable set of files.

  • Like 1

Share this post


Link to post
16 hours ago, dummzeuch said:

That depends. Our internal programs all do that. They aren't installed under program files, though.

That requires write access for the user account to the folder the program is in, and that makes it vulnerable to malware attacks.

Share this post


Link to post
1 hour ago, PeterBelow said:

That requires write access for the user account to the folder the program is in, and that makes it vulnerable to malware attacks.

Yes, I'm aware of that.

Share this post


Link to post

There's no one perfect way that everyone should use. Personally, I use two different approaches:

  • If a program uses a database, I keep all the configuration settings in there except for the path/server/port of what is needed to connect to the database and those are set in an .INI file in the same folder as the application during installation. The installer has admin rights so it can create files under Program Files, and the database settings should never be changed--except by an administrator. In this case the INI filename is simply:
    ChangeFileExt(Application.ExeFilename, '.INI')

     

  • If a program doesn't use a database and has several options to configure when the program is in use by regular users, the INI filename is:
      FAppDataPath := TPath.Combine(TPath.GetPublicPath, ChangeFileExt(ExtractFileName(Application.ExeName), EmptyStr));
      ForceDirectories(FAppDataPath);
      FAppConfigFilename := TPath.Combine(FAppDataPath, ChangeFileExt(ExtractFileName(Application.ExeName), '.ini'));

    This puts the file in a folder under %ProgramData%\MyApp making it global for any users on the computer.

  • Like 1

Share this post


Link to post
On 3/22/2022 at 11:34 AM, dummzeuch said:

It gets even more flexible by allowing to redirect sections or even single entries.

Pretty smart! File redirect is like Git-config's include but pulling specific sections is a more powerful feature.

17 hours ago, corneliusdavid said:

If a program uses a database, I keep all the configuration settings in there except for the path/server/port of what is needed to connect to the database

This is good but requires an account for each user. Moreover, in theory there could be some settings that affect pre-connect state

Share this post


Link to post
22 hours ago, dummzeuch said:

Yes, I'm aware of that.

Are you also aware of the legal repercussions that may have? It's of course OK if you only use the program on your own computers, but if you sell it to clients it opens you up to litigation. If the program is infected on the client's computer and then causes damage there the client could sue you, since the program does not follow accepted safety standards for software. Depends on your countries legislation, of course.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×