none
How to permanently save variable values after program closes RRS feed

  • Question

  • I am programming a basic credits system in c# for my form application. My question is if i have a variable int credits = 9999;

    When i charge them in some process i want to save the new value even if i close the program restart and says 9990 if i used 10 credits. So when i open again the program it saved the charged credits and made them 9990.

    Tuesday, April 30, 2019 11:26 AM

Answers

  • Hello,

    You could save settings to a binary file where in the example below there is one property for credits but you can add more as needed.

    All code below you need to ensure that the namespace for your project replaces my namespace.

    using System;
    
    namespace WindowsFormsApp1
    {
        /// <summary>
        /// This class is were you would put all things to remember
        /// between sessions of your app, currently there is only one
        /// but you can add anything.
        /// </summary>
        [Serializable]
        public class ProgramSettings
        {
    
            public int Credits { get; set; }
        }
    }

    Classes to serialize and deserialize

    using System;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace WindowsFormsApp1
    {
        public class Worker
        {
            public string FileName =>
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.data");
    
            public void Serialize(ProgramSettings pProgramSettings)
            {
                Stream ms = File.OpenWrite(FileName);
    
                var formatter = new BinaryFormatter();
    
                formatter.Serialize(ms, pProgramSettings);
                ms.Flush();
                ms.Close();
                ms.Dispose();
            }
            public ProgramSettings Deserialize()
            {
                var formatter = new BinaryFormatter();
    
                var fs = File.Open(FileName, FileMode.Open);
    
                var obj = formatter.Deserialize(fs);
                var programSettings = (ProgramSettings)obj;
                fs.Flush();
                fs.Close();
                fs.Dispose();
    
                return programSettings;
    
            }
        }
    }

    Note the following uses the latest features of C# e.g. as done in int.TryParse.

    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            private Worker worker = new Worker();
            public Form1()
            {
                InitializeComponent();
                Closing += Form1_Closing;
            }
    
            private void Form1_Closing(object sender, CancelEventArgs e)
            {
                if (int.TryParse(currentCreditsTextBox.Text, out var currentCredits) && int.TryParse(creditsToRemoveTextBox.Text, out var removeCredits))
                {
                    // if there is a rule say to disallow credits to be below zero you need to handle this
                    var programSetting = new ProgramSettings { Credits = currentCredits - removeCredits };
                    worker.Serialize(programSetting);
                }
                else
                {
                    // do nothing as one or both TextBox controls can't represent a int.
                }
            }
            /// <summary>
            /// This code can be in form load, form shown, in a class method or as done
            /// here in a button click event.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void demoButton_Click(object sender, EventArgs e)
            {
                
                if (File.Exists(worker.FileName))
                {
                    var settings = worker.Deserialize();
                    currentCreditsTextBox.Text = settings.Credits.ToString();
                }
                else
                {
                    // first time, give a default value.
                    var programSetting = new ProgramSettings {Credits = 9999};
                    currentCreditsTextBox.Text = "9999";
                    worker.Serialize(programSetting);
                }
            }
        }
    }

    here the top text box is currentCreditsTextBox, under that is creditsToRemoveTextBox

    EDIT: If there are multiple users then you can expand the ProgramSettings class to include a user name and query for a specific user or have one file per users say using their login name .data


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Tuesday, April 30, 2019 3:07 PM
    Moderator
  • Hi Stefan Nachov,

    Thank you for posting here.

    Same way with the MasaSam. I only simplify the code. Use the Properties > Settings. My form name is Test.

     private void Test_Load(object sender, EventArgs e)
            {
                textBox1.Text = Properties.Settings.Default.creditsValue;
            }
    
            private void Test_FormClosed(object sender, FormClosedEventArgs e)
            {
                Properties.Settings.Default.creditsValue = textBox1.Text;
                Properties.Settings.Default.Save();
            }

    Set the value in FormClosed event and load the value in form Load event.

    >>but it doesnt set the new charged value of credits after closing and again starting the program.

    Please try the code above. And if it still does not work, please provide more details. Code with error message would be helpful.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by Stefan Nachov Thursday, May 2, 2019 9:05 AM
    Wednesday, May 1, 2019 2:54 AM
    Moderator

All replies

  • Hello,

     You can design your application to make use of a configuration file, usually

    located in the same directory as the program.  Some programs make use of

    the Registry but that is more complex and could lead to problems.  I think

    the local config file is the better option.

     

     Hope this helps :)

    Tuesday, April 30, 2019 1:17 PM
  • This depends what kind of an application you are building and is this application or user wide value to save.

    One of the simplest way is to use built-in Settings feature. Below is very raw example of Windows Forms application that stores and saves credits value user has given to settings and reloads it.

    User interface looks like this

    Code is

    public partial class Form1 : Form
    {
        private int credits;
    
        public Form1()
        {
            InitializeComponent();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            credits = Settings.Default.Credits;
            textCredits.Text = credits.ToString();
        }
    
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Settings.Default.Credits = credits;
            Settings.Default.Save();
        }
    
        private void buttonSetCredits_Click(object sender, EventArgs e)
        {
            credits = int.Parse(textCredits.Text);
        }
    }

    And the settings file itself looks like:


    • Edited by MasaSam Tuesday, April 30, 2019 1:50 PM
    Tuesday, April 30, 2019 1:45 PM
  • Hello,

    You could save settings to a binary file where in the example below there is one property for credits but you can add more as needed.

    All code below you need to ensure that the namespace for your project replaces my namespace.

    using System;
    
    namespace WindowsFormsApp1
    {
        /// <summary>
        /// This class is were you would put all things to remember
        /// between sessions of your app, currently there is only one
        /// but you can add anything.
        /// </summary>
        [Serializable]
        public class ProgramSettings
        {
    
            public int Credits { get; set; }
        }
    }

    Classes to serialize and deserialize

    using System;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace WindowsFormsApp1
    {
        public class Worker
        {
            public string FileName =>
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.data");
    
            public void Serialize(ProgramSettings pProgramSettings)
            {
                Stream ms = File.OpenWrite(FileName);
    
                var formatter = new BinaryFormatter();
    
                formatter.Serialize(ms, pProgramSettings);
                ms.Flush();
                ms.Close();
                ms.Dispose();
            }
            public ProgramSettings Deserialize()
            {
                var formatter = new BinaryFormatter();
    
                var fs = File.Open(FileName, FileMode.Open);
    
                var obj = formatter.Deserialize(fs);
                var programSettings = (ProgramSettings)obj;
                fs.Flush();
                fs.Close();
                fs.Dispose();
    
                return programSettings;
    
            }
        }
    }

    Note the following uses the latest features of C# e.g. as done in int.TryParse.

    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            private Worker worker = new Worker();
            public Form1()
            {
                InitializeComponent();
                Closing += Form1_Closing;
            }
    
            private void Form1_Closing(object sender, CancelEventArgs e)
            {
                if (int.TryParse(currentCreditsTextBox.Text, out var currentCredits) && int.TryParse(creditsToRemoveTextBox.Text, out var removeCredits))
                {
                    // if there is a rule say to disallow credits to be below zero you need to handle this
                    var programSetting = new ProgramSettings { Credits = currentCredits - removeCredits };
                    worker.Serialize(programSetting);
                }
                else
                {
                    // do nothing as one or both TextBox controls can't represent a int.
                }
            }
            /// <summary>
            /// This code can be in form load, form shown, in a class method or as done
            /// here in a button click event.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void demoButton_Click(object sender, EventArgs e)
            {
                
                if (File.Exists(worker.FileName))
                {
                    var settings = worker.Deserialize();
                    currentCreditsTextBox.Text = settings.Credits.ToString();
                }
                else
                {
                    // first time, give a default value.
                    var programSetting = new ProgramSettings {Credits = 9999};
                    currentCreditsTextBox.Text = "9999";
                    worker.Serialize(programSetting);
                }
            }
        }
    }

    here the top text box is currentCreditsTextBox, under that is creditsToRemoveTextBox

    EDIT: If there are multiple users then you can expand the ProgramSettings class to include a user name and query for a specific user or have one file per users say using their login name .data


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Tuesday, April 30, 2019 3:07 PM
    Moderator
  • Thank you i tried it, but it doesnt set the new charged value of credits after closing and again starting the program.
    Tuesday, April 30, 2019 6:06 PM
  • Hi Stefan Nachov,

    Thank you for posting here.

    Same way with the MasaSam. I only simplify the code. Use the Properties > Settings. My form name is Test.

     private void Test_Load(object sender, EventArgs e)
            {
                textBox1.Text = Properties.Settings.Default.creditsValue;
            }
    
            private void Test_FormClosed(object sender, FormClosedEventArgs e)
            {
                Properties.Settings.Default.creditsValue = textBox1.Text;
                Properties.Settings.Default.Save();
            }

    Set the value in FormClosed event and load the value in form Load event.

    >>but it doesnt set the new charged value of credits after closing and again starting the program.

    Please try the code above. And if it still does not work, please provide more details. Code with error message would be helpful.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by Stefan Nachov Thursday, May 2, 2019 9:05 AM
    Wednesday, May 1, 2019 2:54 AM
    Moderator