Получено из ответа Esailija с исправлениями для поддержки нескольких ключей верхнего уровня.
(function () {
function parseDotNotation(str, val, obj) {
var currentObj = obj,
keys = str.split("."),
i, l = Math.max(1, keys.length - 1),
key;
for (i = 0; i < l; ++i) {
key = keys[i];
currentObj[key] = currentObj[key] || {};
currentObj = currentObj[key];
}
currentObj[keys[i]] = val;
delete obj[str];
}
Object.expand = function (obj) {
for (var key in obj) {
if (key.indexOf(".") !== -1)
{
parseDotNotation(key, obj[key], obj);
}
}
return obj;
};
})();
var obj = {
"pizza": "that",
"this.other": "that",
"alphabets": [1, 2, 3, 4],
"this.thing.that": "this"
}
Выходы:
{
"pizza": "that",
"alphabets": [
1,
2,
3,
4
],
"this": {
"other": "that",
"thing": {
"that": "this"
}
}
}
Я сделал это один раз, надеюсь, это поможет:
bool createdNew;
Mutex m = new Mutex(true, "myApp", out createdNew);
if (!createdNew)
{
// myApp is already running...
MessageBox.Show("myApp is already running!", "Multiple Instances");
return;
}
Я использую это:
private static Mutex _mutex;
private static bool IsSingleInstance()
{
_mutex = new Mutex(false, _mutexName);
// keep the mutex reference alive until the normal
//termination of the program
GC.KeepAlive(_mutex);
try
{
return _mutex.WaitOne(0, false);
}
catch (AbandonedMutexException)
{
// if one thread acquires a Mutex object
//that another thread has abandoned
//by exiting without releasing it
_mutex.ReleaseMutex();
return _mutex.WaitOne(0, false);
}
}
public Form1()
{
if (!isSingleInstance())
{
MessageBox.Show("Instance already running");
this.Close();
return;
}
//program body here
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_mutex != null)
{
_mutex.ReleaseMutex();
}
}
Проверьте код, показанный на на этой странице
. Короче говоря, вы используете перегрузку Mutex ctor(bool, string, out bool)
, которая сообщает вам через параметр out, независимо от того, получили ли вы право собственности на Именованный Mutex. Если вы первый экземпляр, этот параметр будет содержать true после вызова ctor - в этом случае вы будете продолжать, как обычно. Если этот параметр является ложным, это означает, что еще один экземпляр уже получил право собственности /, и в этом случае вы увидите сообщение об ошибке «Другой экземпляр уже запущен». а затем изящно выйти.
static void Main()
{
using(Mutex mutex = new Mutex(false, @"Global\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
GC.Collect();
Application.Run(new Form1());
}
}
Источник: http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
Используйте приложение с таймаутом и настройками безопасности. Я использовал свой собственный класс:
private class SingleAppMutexControl : IDisposable
{
private readonly Mutex _mutex;
private readonly bool _hasHandle;
public SingleAppMutexControl(string appGuid, int waitmillisecondsTimeout = 5000)
{
bool createdNew;
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
_mutex = new Mutex(false, "Global\\" + appGuid, out createdNew, securitySettings);
_hasHandle = false;
try
{
_hasHandle = _mutex.WaitOne(waitmillisecondsTimeout, false);
if (_hasHandle == false)
throw new System.TimeoutException();
}
catch (AbandonedMutexException)
{
_hasHandle = true;
}
}
public void Dispose()
{
if (_mutex != null)
{
if (_hasHandle)
_mutex.ReleaseMutex();
_mutex.Dispose();
}
}
}
и использовал его:
private static void Main(string[] args)
{
try
{
const string appguid = "{xxxxxxxx-xxxxxxxx}";
using (new SingleAppMutexControl(appguid))
{
Console.ReadLine();
}
}
catch (System.TimeoutException)
{
Log.Warn("Application already runned");
}
catch (Exception ex)
{
Log.Fatal(ex, "Fatal Error on running");
}
}
Посмотрите на этот вопрос
Существует ссылка на эту статью: неверно понятый мьютекс , где объясняется использование мьютекса.