1

I am about pull all of my hair at once. Needless to say, I am frustrated. I am coding within Delphi Prism for .NET and currently working to get my application's user-defined properties saved into Application config file. I have setup everything as follows. It is working but some Values are not being saved or retrieved at all. So, I looked into the app.config file thinking they will all be there, but I didn't see any of the values saved in the file match the values that is being retrieved. It only has default values I put into Properties.Designer. Someone did say online that config file will only be updated when you run your application outside of Delphi Prism IDE. And I did, that still didn't work. I even rebooted my computer thinking that maybe Delphi Prism is flaky and it needed a quick break. Even that didn't work.

So, where are the values being saved - in app.config file or in memory?

(my code might be choppy. I am trying to get the basic setup for my app working before I polish the code.)

Here is the image of my Properties.Settings.Designer:

Properties.Settings.Designer

Here is the app.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MillenniaMono.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <userSettings>
        <MillenniaMono.Properties.Settings>
            <setting name="baseDir" serializeAs="String">
                <value>00:00:00</value>
            </setting>
            <setting name="SoftKey" serializeAs="String">
                <value>$6e1eaffa</value>
            </setting>
            <setting name="OnTop" serializeAs="String">
                <value>False</value>
            </setting>
            <setting name="StartExpanded" serializeAs="String">
                <value>True</value>
            </setting>
            <setting name="HideOnStart" serializeAs="String">
                <value>False</value>
            </setting>
            <setting name="DXCommLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="InputBoxLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="MainFormLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="OutputUnitLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="SysErrorDlgLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="UnitDuplicateLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="UnitsLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="UnitSelectLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="CommStatusLocation" serializeAs="String">
                <value>50, 50</value>
            </setting>
            <setting name="UnitsWinSize" serializeAs="String">
                <value>703, 300</value>
            </setting>
            <setting name="DXComm_TypeDX" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_Comport" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_Baud" serializeAs="String">
                <value>1200</value>
            </setting>
            <setting name="DXComm_Parity" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_RetryInt" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_TimeOutDelay" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_ScanTime" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_Offline_Pct" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_Online_Pct" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_ControlCycleCount" serializeAs="String">
                <value>0</value>
            </setting>
            <setting name="DXComm_LockTimeDelay" serializeAs="String">
                <value>0</value>
            </setting>
        </MillenniaMono.Properties.Settings>
    </userSettings>
</configuration>

Here is the code for writing into app.config:

  if ReadWrite then
  begin
      RetryIni := Int32(RetrySpin.value);
      OfflinePct := int32(OfflineSpin.value);
      ScanTime := int32(ScanSpin.value);
      OnlinePct := int32(OnlineSpin.value);
      timeoutDelay := int32(TimeoutSpin.Value);
      ControlCycleCount := int32(ControlSpin.value);
      LockTimeDelay := Int32(LockTime.value);

      with commsetting := Millenniamono.Properties.Settings.Default do
      begin
        commsetting.DXComm_TypeDX := TypeDXCard.SelectedIndex;
        commsetting.DXComm_Comport := Commport.SelectedIndex;
        commsetting.DXComm_Baud:=BaudRate.SelectedIndex;
        commsetting.DXComm_Parity := int32(EvenParity.Checked = true);
        commsetting.DXComm_RetryInt:=RetryIni;
        commsetting.DXComm_TimeOutDelay:=timeOutDelay;
        commsetting.DXComm_ScanTime:=ScanTime;
        commsetting.DXComm_Offline_Pct:=OfflinePct;
        commsetting.DXComm_Online_Pct:=onlinepct;
        commsetting.DXComm_ControlCycleCount:=ControlCycleCount;
        commsetting.DXComm_LockTimeDelay:=LockTimeDelay;
        commsetting.Save;
      end;
  end;

Here is the code reading:

TypeDXCard.SelectedIndex:= commsetting.DXComm_TypeDX;
Commport.SelectedIndex:=CommSetting.DXComm_Comport;

case commsetting.DXComm_Baud of
1200: BaudRate.SelectedIndex:=0;
2400: BaudRate.SelectedIndex:=1;
4800: Baudrate.SelectedIndex:=2;
9600: BaudRate.SelectedIndex:=3;
19200: BaudRate.SelectedIndex:=4;
38400: BaudRate.SelectedIndex:=5;
57600: BaudRate.SelectedIndex:=6;
115200: BaudRate.SelectedIndex:=7;
else BaudRate.SelectedIndex:=0;
end;

case commsetting.DXComm_Parity of 
0: begin EvenParity.Checked:=true; NoneParity.Checked:=false; end;
1: begin NoneParity.Checked:=true; EvenParity.Checked:=false; end;
else begin EvenParity.Checked:=true; NoneParity.Checked:=false; end;
end;

RetrySpin.Value:=Commsetting.DXComm_RetryInt;
RetryIni := RetrySpin.Value;

TimeOutSpin.Value:=CommSetting.DXComm_TimeOutDelay;
TimeOutDelay := TimeOutSpin.Value;

ScanSpin.Value:=CommSetting.DXComm_ScanTime;
ScanTime := ScanSpin.Value;

OfflineSpin.Value:=CommSetting.DXComm_Offline_Pct;
OfflinePct:=OfflineSpin.Value;

OnlineSpin.Value:=Commsetting.DXComm_Online_Pct;
OnlinePct:=OnlineSpin.Value;

Controlspin.Value:=Commsetting.DXComm_ControlCycleCount;
ControlCycleCount:=Controlspin.Value;

LockTime.Value:=Commsetting.DXComm_LockTimeDelay;
LockTimeDelay := LockTime.Value;
  end;

Here is the actual values being displayed or retrieved. I arbitrarily set some values to be saved and read back but it doesn't match what I am seeing in app.config file.

Window

ThN
  • 3,235
  • 3
  • 57
  • 115

2 Answers2

4

User settings are meant as settings that can be altered/saved on a per-user basis. Therefor they are not saved in your app.config but in a new file called user.config and that file is saved under de %APPDATA% directory. On a windows 7 machine it probably looks something like

c:\users\myusername\appdata\local\microsoft\myassemblyname\user.config (there might also be some guid somewhere I can't recall)

The user settings can also be found in the app.config but those values are used as the default values when a new user.config file is created for the first time.

EDIT: Extra info on locating the file. I did a quick test running in the vs debugger for an assembly called DEA.exe and the user.config ended up in:

C:\Users\\AppData\Local\\DEA.vshost.exe_Url_sloja2hil2eiypecefjbp1icc1fo50g4\\user.config

A bit more info can be found in this msdn document (last paragraph on the remarks specifically)

Eddy
  • 5,320
  • 24
  • 40
  • unfortunately I simply can't find the user.config file anywhere in my computer system. I even searched on *.config file and sorted the results based on date and time for today. Still, there are absolutely no config file that got updated for today. Search result shows a lots of administration.config, app.config, ApplicationHost.config and so on. The list is too long to list in the comment. – ThN Aug 19 '11 at 12:51
  • 1
    Download processmonitor at http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx. Set a filter to "operation"-"is"-"writefile" run your app and see where it saves (and let us know, could be usefull for others as well) – Eddy Aug 19 '11 at 13:06
  • Yes!!! Found it. Thank you. Apparently, AppData folder is hidden. So, Windows 7 Search tool skipped it all together. So, my next question is what if you need to deploy your software with pre-defined user.config, do you just take this user.config file and throw it along the exe file. – ThN Aug 19 '11 at 13:25
  • @ Eddy, I downloaded the process monitor program and ran it first before I ran my program. After applying your filter, it displayed my application and where it was writing to. – ThN Aug 19 '11 at 14:32
  • The usersettings in your app.config are used as the default values for any _new_ user.config that gets generated. So those basically serve as your 'pre-defined user.config'. Note that you now also should become aware that if in a later release of your app your settings change that you need to 'upgrade' any previously created user.config from your app (this can't be done by the msi since it can't know what user.config exist) – Eddy Aug 19 '11 at 15:24
  • 1
    @digitalanalog the appdata folder isn't hidden afaik but it's by default excluded from getting indexed (why-oohhh-why) – Eddy Aug 19 '11 at 15:26
  • I'm running on Windows 7 and the AppData folder is a hidden folder. – BlueMonkMN May 14 '14 at 21:02
0

I don't know about Delphi, but at least c# generates a real code file from the settings designer, with content like this

[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("foo")]
public string bar {
    get {
        return ((string)(this["bar"]));
    }
    set {
        this["bar"] = value;
    }
}

I assume Delphi will generate a similar file.
The default value is encoded as an attribute, if nothing is specified in app.config the default value is used. Nothing is written to app.config.
In the c# case the designer also tries to create corresponding default values in app.config, but if they are removed the default value from the DefaultSettingValueAttribute is used.

If you manually create a value in app.config, is that value used?

Albin Sunnanbo
  • 46,430
  • 8
  • 69
  • 108
  • 1
    Delphi Prism is based on Microsoft Visual Studio. So, I am assuming they all in similar fashion. – ThN Aug 18 '11 at 20:06