문제

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 ?

도움이 되었습니까?

해결책 3

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
    };
}       

다른 팁

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.

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top