Поддерживать значение переменной между запусками программы
У меня есть простое консольное приложение на C#, которое планируется через каждые 5 минут. Каждый вызов программы требует вывода последнего запуска.
Сейчас я использую текстовый файл и сохраняю в нем результат. в следующий раз, когда он запустится, он откроет текстовый файл и узнает результаты предыдущего запуска.
Есть ли другой способ сделать это, который не требует такого текстового файла? Как поддерживать переменную сеанса и т.д.?
3 ответа
Сначала используйте решение блокировки мьютекса, чтобы приложение одновременно запускало только один экземпляр.
затем создайте сериализуемый класс для хранения состояния приложения и вспомогательный класс для загрузки и сохранения его в файл.
[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
};
}
Вы можете использовать файл настроек. Просто добавьте файл настроек в ваш проект и сохраняйте значение, которое вы хотите сохранить, каждый раз, когда программа закрывается. Когда программа запустится, проверьте значение в файле настроек.
Ну, вы должны сохранить данные где-нибудь. Консольные приложения не имеют переменных сеанса (или даже сеансов). Вы, вероятно, имеете в виду переменную среды. Если вы храните его в переменной окружения, программа должна будет работать из той же среды (то есть из того же окна консоли). В случае сбоя машины переменные среды теряются. Вы, вероятно, лучше с файлом.
Если это будет выполняться каждые 5 минут, не могли бы вы дать программе спать, пока она не запустится снова? Тогда данные будут доступны в памяти. Это все еще проблема, если машина дает сбой, поэтому вам все равно может понадобиться сохранить файл в качестве резервной копии.
Если вы не хотите, чтобы пользователи видели файл, и это не слишком много данных (хотя несколько байтов K, вероятно, будут работоспособны), как предложил @Quintin Robinson, вы можете использовать реестр. Просто убедитесь, что вы пишете в область, которая логична и где у вас есть необходимые разрешения.
Если вы не хотите, чтобы пользователи могли видеть, что находится в файле, вы можете зашифровать содержимое, чтобы сделать его нечитаемым. Если вы используете шифрование, вам потребуется ключ для дешифрования локально, чтобы опытный или решительный злоумышленник все же смог получить доступ к файлу. Может быть, лучше просто сжать данные и назвать это хорошо.
Если вы не хотите, чтобы пользователи могли легко изменять содержимое файла, вы можете сохранить контрольную сумму, хэш или HMAC с данными. Вы должны будете проверить это локально, что означает, что это может быть атаковано, но должно остановить случайного пользователя от взлома.
Конечно, вы можете объединить хранение реестра, шифрование и контрольную сумму, в зависимости от ваших потребностей и проблем.
Я подумывал упомянуть PStor и CryptProtectData/CryptUnprotectData, но потом понял, что их безопасность основана на USER и поэтому здесь не поможет.
Если машина подключена к Интернету, вы могли бы рассмотреть облачное хранилище, хотя я понятия не имею, подойдет ли это для вашего приложения.