我有一个简单的c#控制台应用程序,每隔5分钟安排一次。每次调用程序都需要上次运行的输出。
我现在正在做的是使用文本文件并将结果存储在其中。下次运行时,它会打开文本文件并知道上一次运行的输出。
还有其他方法可以不需要任何此类文本文件吗? 喜欢维护会话变量等吗?
答案 0 :(得分:5)
您可以使用设置文件。只需将项目文件添加到项目中,并在每次程序关闭时保存要存储的值。当程序启动时,它会检查设置文件中的值。
答案 1 :(得分:4)
嗯,你必须在某处保存数据。控制台应用程序没有会话变量(甚至是会话)。你可能意味着环境变量。如果将其存储在环境变量中,则程序必须从相同的环境(即来自同一控制台窗口)运行。如果机器崩溃,环境中的变量就会丢失。你可能最好用一个文件。
如果每隔5分钟运行一次,您是否可以让程序休眠直到需要再次运行?然后数据将在内存中可用。如果机器崩溃仍然存在问题,因此您仍可能需要将文件保留为备份。
如果你不希望用户看到一个文件,并且它不是那么多的数据(虽然几个K字节可能是可行的),正如@Quintin Robinson建议的那样,你可以使用注册表中。只需确保您正在写一个合乎逻辑的区域以及您拥有正确权限的区域。
如果您不希望用户能够看到文件中的内容,您可以对内容进行加扰,使其无法读取。如果您使用加密,则需要在本地解密密钥,以便熟练或坚定的攻击者仍能够获取该文件。最好只压缩数据并称之为好。
如果您不希望用户能够轻松更改文件中的内容,则可以使用数据存储校验和,哈希或HMAC。你必须在本地进行验证,这意味着这可能会受到攻击,但应该阻止临时用户进行攻击。
当然,根据您的需求和关注点,您可以将注册表存储,加扰和校验和结合起来。
我考虑过提及PStor和CryptProtectData / CryptUnprotectData,但后来我意识到他们的安全性基于 USER ,所以在这里没有帮助。
如果机器已连接到互联网,您可以考虑云存储,但我不知道这是否适合您的应用。
答案 2 :(得分:3)
首先使用mutex lock解决方案强制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
};
}