5

我有一个简单的 c# 控制台应用程序,每 5 分钟安排一次。程序的每次调用都需要最后一次运行的输出。

我现在正在做的是使用文本文件并将结果存储在其中。下次运行时,它会打开文本文件并知道上一次运行的输出。

还有其他不需要任何此类文本文件的方法吗?像维护会话变量等?

4

3 回答 3

6

您可以使用设置文件。每次程序关闭时,只需将设置文件添加到您的项目并保存您要存储的值。当程序启动时,它会检查设置文件中的值。

于 2012-11-21T02:08:17.760 回答
4

好吧,您必须将数据保存在某处。控制台应用程序没有会话变量(甚至会话)。您可能是指环境变量。如果将其存储在环境变量中,则程序必须从相同的环境(即从相同的控制台窗口)运行。如果机器崩溃,环境变量就会丢失。您可能最好使用文件。

如果它每 5 分钟运行一次,你能让程序休眠直到它需要再次运行吗?然后数据将在内存中可用。如果机器崩溃仍然是一个问题,因此您仍然可能需要保留文件作为备份。

如果您不希望用户看到一个文件,并且它不是太多数据(尽管几个 K 字节可能是可行的),正如@Quintin Robinson 建议的那样,您可以使用注册表。只需确保您正在写入一个合乎逻辑且您拥有正确权限的区域。

如果您不希望用户能够看到文件中的内容,您可以打乱内容以使其不可读。如果您使用加密,您将需要本地密钥来解密,以便熟练或坚定的攻击者仍然能够获取文件。最好只压缩数据并称其为好。

如果您不希望用户能够轻松更改文件中的内容,您可以将校验和、哈希或 HMAC 与数据一起存储。您必须在本地验证它,这意味着这可能会受到攻击,但应该阻止临时用户进行位黑客攻击。

当然,您可以结合注册表存储、加扰和校验和,这取决于您的需要和关注点。

我考虑过提到 PStor 和 CryptProtectData/CryptUnprotectData 但后来我意识到它们的安全性是基于USER的,所以在这里没有帮助。

如果机器连接到 Internet,您可以考虑云存储,但我不知道这是否适合您的应用程序。

于 2012-11-21T02:04:10.230 回答
3

首先使用互斥锁解决方案强制app同时只运行一个实例。

然后创建一个可序列化的类来保存应用程序状态和一个辅助类来加载并将其保存到文件中。参见示例:

[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();
            }
        }

    }
}

然后从您的应用加载并保存状态:

    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
    };
}       
于 2012-11-21T02:22:53.677 回答