[4.6.1] Custom INIs files read & write problems

I like load and the read/write a custom ini file, i have created in my “Config” folder a file called “DefaultGameSettings.ini” with this content:

[Profile]
pAccountName=Hello

and a object class with:
GameSettingsConfig.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Object.h"
#include "GameSettingsConfig.generated.h"

/**
* 
*/
UCLASS( Config = GameSettings )
class GAMENAME_API UGameSettingsConfig : public UObject
{
GENERATED_BODY()

UPROPERTY( Config )
FString pAccountName;


};

GameSettingsConfig.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "GAMENAME.h"
#include "GameSettingsConfig.h"

with this i get at load the editor the generation of the ini files in the Saved folder but are empty with 2 space lines only in the sub Windows folder.
Then to read & write the value i using the Rama’s plugin (39) Rama's Extra Blueprint Nodes for You as a Plugin, No C++ Required! - Blueprint - Unreal Engine Forums! with some changes, adding support to read & write data from the custom ini file:

VictoryBPFunctionLibrary.h

/** Get Custom Config Var! These are stored in Saved/Config/Windows/GameSettings.ini */
UFUNCTION(BlueprintPure, Category = "VictoryBPLibrary|Config Reader")
static FString ConfigGetCustomConfigVar_String(FString SectionName, FString VariableName);

/** Set Custom Config Var! These are stored in Saved/Config/Windows/GameSettings.ini */
UFUNCTION(BlueprintCallable, Category = "VictoryBPLibrary|Config Writer")
static void ConfigSetCustomConfigVar_String(FString SectionName, FString VariableName, FString Value);

VictoryBPFunctionLibrary.cpp

FString UVictoryBPFunctionLibrary::ConfigGetCustomConfigVar_String(FString SectionName,FString VariableName)
{
if(!GConfig) return "";
//~~~~~~~~~~~

FString Value;
GConfig->GetString(
*SectionName,
*VariableName,
Value,
FString( TEXT( "GameSettings" ) )
);
return Value;
}

void UVictoryBPFunctionLibrary::ConfigSetCustomConfigVar_String(FString SectionName,FString VariableName, FString Value)
{
if(!GConfig) return;
//~~~~~~~~~~~

GConfig->SetString(
*SectionName,
*VariableName,
*Value,
FString( TEXT( "GameSettings" ) )
);
GConfig->Flush( false, FString( TEXT( "GameSettings" ) ) );
}

Then in the Level Blueprint i place this two nodes, the get attached to one event tick and to print to print in the screen the value and the set to the Begin place node with the info of “Profile” & “pAccountName” and “HelloWorld”.

Problems:
1º- When i get the value give me “” = null, but if i set the value to for example “HelloWorld” at get i get the “HelloWorld” and if i restart the editor/engine and only get the value i get the “HelloWorld” WHERE IS STORED that value because don’t is in my .ini and don’t is in any file of my Saved folder or in Config/ or in the engine folder, then WHERE IS?

2º- How make to work well with my custom ini file, because is created in saved but is empty and my value don’t store in my custom .ini.

Hello

I guess this isn’t actual as it has been asked almost a year ago, but i’ve encountered the same problem recently and found a solution (thanks to Rama’s tutorial on configs and stuff :slight_smile: A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums,Read%26_Write_to_Config_Files#Of_Great_Importance)

All you need to do is to call ‘Flush’ BEFORE reading from config file and AFTER writing to it.

For example you are working with Game.ini config. Then you should write (it’s C++ only, i’ve wrapped this function call in a simple blueprint function library for using along with Rama’s Victory plugin):

Before reading:

GConfig->Flush(true, GGameIni);

After writing:

GConfig->Flush(false, GGameIni);

The difference is only in first bool parameter.
Now all the values will be updated properly and you’re good to go :slight_smile:

1 Like

Sorry but that don’t solve my problem.

someone can help me with this please ?

Thanks a lot Revenvik , that worked for me!

I will resurrect this post for the sake of it being at the top in google results on this topic, and while is has a partial answer that points to Rama’s “use the default config files” tutorial, I believe it is not fully answered with regards to using a fully custom .ini file. (Which actually uses the same functions as Rama’s tutorial just with different parameters)
I’m not sure if it it still something the original poster is looking for, but it might save someone else some time.

First: an empty file automatically gets created when you type: UCLASS( Config = GameSettings )
It will first try to find that file in /saved/config/windows/ and then in /config/DefaultGamesettings.ini, and then a few others to read that value. (Check out https://docs.unrealengine.com/latest/INT/Programming/Basics/ConfigurationFiles/index.html for details on hierarchy. Also notice that:

 UPROPERTY( Config )
 FString pAccountName;

Will only read the config file entry, you need to call SaveConfig() to write it back to the config file. This way of reading/writing will assume the key is stored in a config file that looks like this:

[/script/MyProject.MyClass]
pAccountName = MyTestName

Now secondly, the part of your code where you try to open a config file directly:
In your code, you write: FString( TEXT( “GameSettings” ) )
and try to use that as a location. Now it should be noticed that this parameter expects a path to a file, not just a name. (So it differs to the UCLASS(Config = myfilename) approach.) If you only supply a name, it tends to use “C:\Path\To\CompiledUnreal\Engine\Binaries\Win64” as folder. (Which is not anywhere near where you’d expect it, but that might be where your file got written to in regards to your “WHERE IS STORED that value” question.)

Instead, you should use something like this:

FString GameSettingsFile = FPaths::GeneratedConfigDir().Append(TEXT("GameSettings.ini")); 
FString Value = TEXT("");

GConfig->GetString(TEXT("Profile"), TEXT("pAccountName"), Value, GameSettingsFile);

Which will try to read /saved/config/GameSettings.ini and in that find the category Profile and the key pAccountName exactly how you had them listed in your original post (copied below for clearity).

 [Profile]
 pAccountName=Hello

Keep in mind that while this answer uses the GeneratedConfigDir, which is ok for user configs you create on the fly (like indeed, saving account names users entered), there are more directories to use and if you use something like the project root, you can make your own path from there. See the https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Misc/FPaths/index.html page for which standard Game***Dir() functions there are.

Writing out variables of course uses GConfig->SetString() instead of GetString, and in that case one should take care to flush the results through:

 GConfig->Flush(false,GameSettingsFile);

Of course assuming GameSettingsFile is a path to a file as shown in the GetString example above.

Finally, the “before reading” GConfig->Flush(true, GameSettingsFile); mentioned in another answer is only useful if you first write to the files (as far as I know).

Well, that should be it. Hopefully someone will get some use out of this. :slight_smile:

I have experienced a similar problem with Standalone Game using 4.18.3. After debugging the code and looking at FConfigFile::Write(…), I’ve found out that the reason why Flush() doesn’t help and INIs are not written is “-Multiprocess” command line parameter standalone game is launched with.

I’ve found a solution in the same line of code: you have to add “-MultiprocessSaveConfig” command line parameter to pass that check. In order to do that, press drop-down arrow near “Play” button on main editor toolbar, go to “Advanced Settings…”, find “Play in Standalone Game” section, “Additional Launch Parameters” text box and paste “-MultiprocessSaveConfig” (without quotes) there.

Not sure how good this solution is since writing configs in the multiprocess environment was probably disabled for a reason, but it works for me for now.