6

I have a simple c# console application that is scheduled after every 5 mins. Every invocation of the program requires the output of the last run.

What I am doing right now is using a text file and store the result in it. next time when it runs it opens the text file and know the output of the previous run.

Is there any other way to do it that wont require any such text file ? Like maintaining a session variable etc ?

pylover
  • 7,670
  • 8
  • 51
  • 73
Akshay J
  • 5,362
  • 13
  • 68
  • 105
  • 1
    You could use a myriad of methods; database, registry, arbitrary file storage, etc. Is there a reason to deviate from the text file storage mechanism? – Quintin Robinson Nov 21 '12 at 02:02
  • I'm with @QuintinRobinson, it would help to understand why you think a file is not the best solution. – jimhark Nov 21 '12 at 02:06
  • its because I dont want the users to see there is one text file my program is creating. Sleeping the program seems like a good idea. – Akshay J Nov 21 '12 at 02:09
  • @QuintinRobinson, most enterprise solutions are using pid lock-file to ban concurrent execution. why you are think IO-File is not good? – pylover Nov 21 '12 at 04:54
  • @Akshay. look at my answer, the file will be created in appdata folder. there is a good place for application's data. you can encrypt the file also. – pylover Nov 21 '12 at 04:56
  • @pylover I didn't say anything of that nature, not sure where you got that impression from. – Quintin Robinson Nov 21 '12 at 05:28

3 Answers3

7

You could use a settings file. Just add a Settings File to your project and save the value you want to store, each time the program closes. When the program starts have it check the value in the settings file.

FrostyFire
  • 3,212
  • 3
  • 29
  • 53
4

Well you have to save the data somewhere. Console apps don't have session variables (or even sessions). You probably mean environment variable. If you store it in an environment variable, the program will have to run from the same environment (i.e. from the same console window). If the machine crashes the environment vars are lost. You're probably better off with a file.

If this runs every 5 minutes, could you let the program sleep till it needs to run again? Then the data would be available in memory. It's still a problem if the machine crashes, so you still may need to keep a file as a backup.

If you don't want the users to see a file, and it's not too much data (though several K bytes would probably be workable), as @Quintin Robinson suggested, you could use the registry. Just make sure you're writing to an area that's logical and where you have the right permissions.

If you don't want the users to be able to see what's in the file you could scramble the contents so as to make it unreadable. If you use encryption, you'll need the key locally to decrypt so a skilled or determined attacker will still be able to get at the file. It may be better to just compress the data and call it good.

If you don't want the users to be able to easily change what's in the file you could store a checksum, hash, or HMAC with the data. You'll have to verify it locally, which means this can be attacked, but should stop a casual user from bit-hacking.

Of course you can combine registry storage, scrambling and checksum, depending on your needs and concerns.

I considered mentioning PStor and CryptProtectData/CryptUnprotectData but then I realized their security is USER based and so will not help here.

If the machine is connected to the Internet you could consider cloud storage, though I have no idea if that would be appropriate for your application.

jimhark
  • 4,938
  • 2
  • 27
  • 28
4

First use mutex lock solution to force app to run only one instance at same time.

then create a serializable class to hold the app state and a helper class to load and save it to a file.see example:

[XmlRoot("RegexTesterPersistantSettings")]
[Serializable]
public class State
{
    public State()
    {
        this.Pattern = string.Empty;
        this.TestString = string.Empty;
        this.Options = 0;
    }
    [XmlElement("Pattern")]
    public string Pattern{get;set;}

    [XmlElement("TestString")]
    public string TestString{get;set;}

    [XmlElement("Options")]
    public int Options { get; set; }

    public override int GetHashCode()
    {
        return this.Options.GetHashCode() ^ this.Pattern.GetHashCode() ^ this.TestString.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        State anotherState = obj as State;
        if (anotherState == null)
        {
            return false;
        }

        return this.Equals(anotherState);
    }

    public bool Equals(State anotherState)
    {
        return this.GetHashCode() == anotherState.GetHashCode();
    }

    public static bool operator ==(State a, State b)
    {
        // If both are null, or both are same instance, return true.
        if (System.Object.ReferenceEquals(a, b))
        {
            return true;
        }

        // If one is null, but not both, return false.
        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }
        return a.Equals(b);
    }

    public static bool operator !=(State a, State b)
    {
        return !a.Equals(b);
    }

}

public class PersistantHelper
{
    private string filename;
    private State _state;

    public PersistantHelper(string xmlFilename = "RegexTesterSettings")
    {
        string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        this.filename  = Path.Combine(appDataPath, xmlFilename);
    }

    private XmlSerializer _serializer;
    private XmlSerializer Serializer
    {
        get
        {
            if (this._serializer == null)
            {
                this._serializer = new XmlSerializer(typeof(State));
            }
            return this._serializer;
        }
    }

    private void SaveState(State state)
    {
        if (File.Exists(this.filename))
        {
            File.Delete(this.filename);
        }
        var stream  = new FileStream(this.filename,  FileMode.OpenOrCreate, FileAccess.Write,FileShare.None);
        this.Serializer.Serialize(stream, state);
        stream.Close();
    }

    public State State
    {
        get
        {
            if (this._state == null)
            {
                this._state = this.GetState();
            }
            return this._state;
        }
        set 
        {
            if (this.State != value)
            {
                this.SaveState(value);
            }
        }
    }

    private State dummyState = new State() { Options = 0 };
    private State GetState()
    {
        if (!File.Exists(this.filename))
        {
            return this.dummyState;
        }
        Stream stream = null;
        try
        {
            stream = new FileStream(this.filename, FileMode.Open, FileAccess.Read,FileShare.None);
            var o = this.Serializer.Deserialize(stream);
            return (State)o;
        }
        catch
        {
            return this.dummyState;
        }
        finally
        {
            if (stream != null)
            {
                stream.Close();
            }
        }

    }
}

then load and save the state from your app:

    private PersistantHelper persistantHelper;
    public frmTester()
    {
        InitializeComponent();
        this.persistantHelper = new PersistantHelper();
        .
        .
        .
    }

private void LoadPersistantData()
{
    State state = this.persistantHelper.State;
    this.txtPattern.Text = state.Pattern;
    this.txtTest.Text = state.TestString;
    foreach (Control c in this.pnlOptions.Controls)
    {
        if (c is CheckBox)
        {
            var chk = c as CheckBox;
            int tag = int.Parse(c.Tag.ToString());
            chk.Checked = (state.Options & tag) == tag;
        }
    }
}


private void SavePersistantData()
{
    this.persistantHelper.State = new State()
    {
        Options = (int)this.GetOptions(),
        Pattern = txtPattern.Text,
        TestString = txtTest.Text
    };
}       
Community
  • 1
  • 1
pylover
  • 7,670
  • 8
  • 51
  • 73
  • 1
    I don't know why this is the accepted answer. It's way over engineered. The original question also says nothing about concurrent processes. – Sam Aug 11 '15 at 12:45
  • Without thinking about concurrency , there is no guaranty, it may fails. – pylover Aug 12 '15 at 15:25