Как вызвать win32 CreateMutex из .Net

Я успешно создал мьютекс .net следующим образом: SingleIns = new Mutex(true, AppName); некоторое время. Он работает в XP, Vista, но, видимо, не в Windows7. Поэтому мне нужно сделать вызов взаимодействия с библиотекой Win32, чтобы другие компоненты Com могли идентифицировать мьютекс. Я нашел следующий код, но файл Win32Calls. не найден... нужна ли мне сборка или ссылка? Заранее спасибо,

Найден код из: http://www.pinvoke.net/default.aspx/kernel32/CreateMutex.html

с помощью System.Runtime.InteropServices;

    [DllImport("kernel32.dll")]
    public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);


       // create IntPtrs for use with CreateMutex()
        IntPtr    ipMutexAttr = new IntPtr( 0 );
        IntPtr    ipHMutex = new IntPtr( 0 );

        try
        {
            // Create the mutex and verify its status BEFORE construction
            // of the main form.

            ipHMutex = Win32Calls.CreateMutex( ipMutexAttr,
                true, "CompanyName_AppName_MUTEX" );

            if (ipHMutex != (IntPtr)0)
            {
                // check GetLastError value (MUST use this call. See MSDN)

                int iGLE = Marshal.GetLastWin32Error();

                // if we get the ERROR_ALREADY_EXISTS value, there is
                // already another instance of this application running.

                if (iGLE == Win32Calls.ERROR_ALREADY_EXISTS)
                    // So, don't allow this instance to run.
                    return;
            }
            else    
            {    // CreateMutex() failed.
                // once the app is up and running, I log the failure from
                // within the frmMain constructor.
                bool m_bMutexFailed = true;
            }

            // construct the main form object and
            //form = new frmMain();

            // run the app.
            //Application.Run( form );

        }
        catch( Exception oEx )
        {
            //...handle it...
        }
        finally
        {
            // release the mutex
            if (ipHMutex != (IntPtr)0)
                Win32Calls.ReleaseMutex( ipHMutex );

            // cleanup the main form object instance.
            if (form != null) {
                form.Dispose();
            }
        }
    }

person mytwocents    schedule 15.12.2009    source источник
comment
Хм. Я только что удалил часть Win32Calls из Win32Calls.CreateMutex и вызвал CreateMutex напрямую... похоже, это может сработать   -  person mytwocents    schedule 15.12.2009
comment
У вас 64-битная версия Windows 7? .NET Mutex в основном должен работать в Windows 7 так же, как и в предыдущих версиях.   -  person Dirk Vollmar    schedule 15.12.2009
comment
Это лучший справочник... msdn.microsoft. com/ru-ru/library/   -  person mytwocents    schedule 15.12.2009
comment
Да, это 64-битная машина Win7...   -  person mytwocents    schedule 15.12.2009
comment
Работает ли мьютекс .NET должным образом, если вы установите целевую платформу «x86»? То, что вы видите, также может быть проблемой 32/64-битного взаимодействия (просто идея, поскольку вы упомянули COM).   -  person Dirk Vollmar    schedule 15.12.2009


Ответы (3)


Он не компилируется, потому что объявление CreateMutex не находится в пространстве имен Win32Calls. Следующая проблема заключается в том, что он по-прежнему не будет работать должным образом, поскольку в объявлении [DllImport] отсутствует назначение свойства SetLastError. Требуется, чтобы Marshal.GetLastWin32Error() возвращал ошибку.

Немного перемотав назад, использование класса Mutex в Win7 должно работать без проблем. Единственный режим сбоя, о котором я могу думать, - это отсутствие префикса имени мьютекса «Global\», чтобы мьютекс был виден во всех сеансах. Это немного отдаленно.

Более того, вы пытаетесь сделать что-то, что уже очень хорошо поддерживается в среде .NET. Проект + Добавить ссылку, выберите Microsoft.VisualBasic. Сделайте так, чтобы ваш код Program.cs выглядел так:

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

namespace WindowsFormsApplication1 {
  class Program : WindowsFormsApplicationBase {
    [STAThread]
    static void Main(string[] args) {
      var prog = new Program();
      prog.EnableVisualStyles = true;
      prog.IsSingleInstance = true;
      prog.MainForm = new Form1();
      prog.Run(args);
    }
  }
}

Дополнительным преимуществом этого подхода является то, что он автоматически устанавливает фокус на запущенный экземпляр вашей программы, когда пользователь запускает ее снова. И вы можете переопределить метод OnStartupNextInstance, чтобы узнать, какие аргументы командной строки использовались, и ответить соответствующим образом.

person Hans Passant    schedule 15.12.2009

Если это может вам помочь, .NET Framework уже предоставляет оболочку объекта мьютекса Win32. См. System.Threading.Mutex. Присутствуют все основные функции, включая возможность использования префиксов, таких как "Global\".

person Jason Kresowaty    schedule 15.12.2009
comment
Проблема заключается в том, что .Net Mutex, который работает для XP и Vista, не обнаруживается неуправляемой программой (c++) для Windows 7. В Windows 7 GetLastError() всегда возвращает ERROR_SUCCESS независимо от того, существует мьютекс или нет. Итак, я пытаюсь изменить способ вызова мьютекса, чтобы он соответствовал собственному коду С++. ПРИМЕЧАНИЕ: мьютекс .net для .net отлично работает в Windows 7. Мьютекс .Net для взаимодействия с мьютексом С++ - это то, что терпит неудачу... может быть на стороне С++. - person mytwocents; 15.12.2009
comment
Я думаю, проблема не в том, что мьютекс не создается общепризнанным способом в Windows 7, поскольку его создает служба. Я добавил Global\ к имени мьютекса, так как в некоторых сообщениях было указано, что это сработало для них. Однако это тоже не работает для меня. (Мьютекс, созданный службой, не отображается в дескрипторе поиска ProcessExplorer, но я знаю, что он там есть, потому что, если я запускаю ту же программу, мьютекс предупреждает, что он уже создан.) Microsoft, что происходит со службами и мютекстами? - person mytwocents; 17.12.2009
comment
В моих тестах это похоже на пространство пользователя. - person BananaAcid; 21.10.2018

Должно быть так же просто, как:

private static System.Threading.Mutex _mutex = null;

const string guid = "{...GUID...}";
bool createdNew;

_mutex = new Mutex(true, guid, out createdNew);

if (!createdNew) {
    // it is in use already
}

общесистемное создание мьютекса - право собственности: https://stackoverflow.com/a/3111740/1644202

person BananaAcid    schedule 21.10.2018