Как определить, работает ли предыдущий экземпляр моего приложения?

Вот один из способов сделать это, просто установите переменную $ multi на то, что вы используете ....

// (?) could have more than one domain match true / false

$multi = FALSE;

while ( $row = $stmt->fetch ( ) )
{
    // loop through all domains

    $trimmed = $row['product'];

    foreach ( $domains as $domain )
    {
        if( preg_match ( "/{$domain['domain']}/i", $trimmed ) )
        {
            $trimmed = str_replace ( $domain['domain'], '', $trimmed );

            if ( $multi === FALSE )
            {
                break;
            }
        }
    }

    $table[$i]['product'] = $trimmed;
}
25
задан abatishchev 30 December 2011 в 08:04
поделиться

10 ответов

Jeroen already answered this, but the best way by far is to use a Mutex... not by Process. Here's a fuller answer with code.

Mutex mutex;

try
{
   mutex = Mutex.OpenExisting("SINGLEINSTANCE");
   if (mutex!= null)
   {
      Console.WriteLine("Error : Only 1 instance of this application can run at a time");
      Application.Exit();
   }
}
catch (WaitHandleCannotBeOpenedException ex)
{
   mutex  = new Mutex(true, "SINGLEINSTANCE");
}

Also bear in mind that you need to run your Application in some sort of Try{} Finally{} block. Otherwise if you're application crashes without releasing the Mutex then you may not be able to restart it again later.

17
ответ дан 28 November 2019 в 20:49
поделиться

The most simple (and reliable) way to do this, is using a Mutex. Use the WaitOne method of the Mutex class to wait until the mutex becomes available. An added advantage, this will not require any infinite loops

4
ответ дан 28 November 2019 в 20:49
поделиться

You can search process names of existing system process. For example code, see this blog post.

You can also used a named system Mutex to see if your process is already running.
Here is some sample code. This tends to be more reliable in my experience, and is much simpler, more understandable code.

2
ответ дан 28 November 2019 в 20:49
поделиться

This article talks about it: Prevent a second process instance from running. It's in VB.net but you can convert it.

The problem in writing a generic function that checks whether the current application is already running comes from the fact that the ProcessName property of the Process object seems to be limited to 15 characters, so longer process names are truncated.
A safer way to retrieve a process name is to get the filename of its main module and dropping the extension. The following reusable routine uses this approach:

Function AppIsAlreadyRunning() As Boolean
    ' get the filename of the main module
    Dim moduleName As String = Process.GetCurrentProcess.MainModule.ModuleName

    ' discard the extension to get the process name
    Dim procName As String = System.IO.Path.GetFileNameWithoutExtension(moduleName)

    ' return true if there are 2 or more processes with that name
    If Process.GetProcessesByName(procName).Length > 1 Then
        Return True
    End If
End Function
2
ответ дан 28 November 2019 в 20:49
поделиться
  • Попробуйте использовать Eval вместо Bind для ImageUrl - это односторонняя привязка.

  • Если у вас все еще есть проблемы,

2
ответ дан 28 November 2019 в 20:49
поделиться

You can use Process.GetProcessesByName("MyProcessName"); in the System.Diagnostics namespace to check if there is an instance of your process running.

EDIT: Very good observations in the comments! This is a (very) simplistic way of doing it, and certainly doesn't cover all the bases.

1
ответ дан 28 November 2019 в 20:49
поделиться

Using a kernal object is the only correct way to implement single instance protection in Windows.

This statement:

mutex = Mutex.OpenExisting("SINGLEINSTANCE");

won't work if someone else copies this line from Stackoverflow and runs their program before your program, since that other guy grabbed "SINGLEINSTANCE" before you did. You want to include a GUID in your mutex name:

mutex = Mutex.OpenExisting("MyApp{AD52DAF0-C3CF-4cc7-9EDD-03812F82557E}");

This technique will prevent the current user from running more than one instance of your program, but will not prevent another user from doing so.

To ensure that only one instance of your application can run on the local computer, you need to do this:

mutex = Mutex.OpenExisting("Global\MyApp{AD52DAF0-C3CF-4cc7-9EDD-03812F82557E}");

See the help for the CreateMutex api.

1
ответ дан 28 November 2019 в 20:49
поделиться

В одном из моих проектов я использовал SingleInstance Component

0
ответ дан 28 November 2019 в 20:49
поделиться

Другой способ сделать это - привязать адрес к локальной машине (как это делал бы прослушиватель TCP). Только один процесс одновременно может связываться с комбинацией порт / адрес. Поэтому выберите порт на адаптере обратной связи и получите его.

Это имеет приятные побочные эффекты:

  • Работает, даже если кто-то переименовывает исполняемый файл
  • Сбрасывает себя при сбое приложения
  • переносимый на другие операционные системы

С другой стороны, он может потерпеть неудачу, если есть другое приложение, которое связывается с этим конкретным портом.


В соответствии с запросом, некоторый код для привязки к адресу / порту приведен ниже. Это сорвано с чего-то другого. Это неполно, но необходимые биты здесь.

using System.Net;
using System.Net.Sockets;

[...]

// Make up a number that's currently unused by you, or any 
// well-known service. i.e. 80 for http, 22 for ssh, etc..
int portNum = 2001;  

// This binds to any (meaning all) adapters on this system 
IPAddress ipAddress = IPAddress.Any;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portNum);
Socket listener = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Tcp );

// The next statement will throw an exception if anyone has done this Bind!
listener.Bind(localEndPoint);

Пока слушатель не является сборщиком мусора (выпадает из области видимости) или программа не завершается: этот порт на этом адаптере ваш и только ваш. Если что-то случится с слушателем , тогда это станет доступным для использования кем-то другим. Для целей блокировки, вы, вероятно, должны иметь слушателя где-то статичным.

-3
ответ дан 28 November 2019 в 20:49
поделиться

Правильный способ использования мьютекса для этой цели:

private static Mutex mutex;

static void Main()
{
    // STEP 1: Create and/or check mutex existence in a race-free way
    bool created;
    mutex = new Mutex(false, "YourAppName-{add-your-random-chars}", out created);
    if (!created)
    {
        MessageBox.Show("Another instance of this application is already running");
        return;
    }

    // STEP 2: Run whatever the app needs to do
    Application.Run(new Form1());

    // No need to release the mutex because it was never acquired
}

Приведенный выше способ не работает для обнаружения того, что несколько пользователей на одной машине запускают приложение под разными учетными записями. Аналогичный случай, когда процесс может работать как под хостом службы и автономно. Чтобы это работало, создайте мьютекс следующим образом:

        var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
        var mutexsecurity = new MutexSecurity();
        mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow));
        mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.ChangePermissions, AccessControlType.Deny));
        mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.Delete, AccessControlType.Deny));
        _mutex = new Mutex(false, "Global\\YourAppName-{add-your-random-chars}", out created, mutexsecurity);

Здесь есть два отличия - во-первых, мьютекс должен быть создан с правами безопасности, позволяющими другим учетным записям пользователей открывать/получать его. Во-вторых, имя должно иметь префикс "Global" в случае служб, работающих под хостом службы (не уверен насчет других пользователей, работающих локально на той же машине).

24
ответ дан 28 November 2019 в 20:49
поделиться