如何从.Net调用win32 CreateMutex

时间:2009-12-15 00:33:34

标签: .net com winapi interop mutex

我已经成功创建了这样的.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();
            }
        }
    }

3 个答案:

答案 0 :(得分:2)

它不起作用是因为您的CreateMutex声明不在Win32Calls命名空间中。您的下一个问题是它仍然无法工作,因为您忘记在[DllImport]属性中设置SetLastError属性。需要使Marshal.GetLastWin32Error()返回错误。

使用Win7中的Mutex类重绕一点应该没有问题。我能想到的唯一失败模式是没有为互斥锁名称加上“Global”前缀,因此互斥锁在所有会话中都可见。那有点偏僻。

更重要的是,您正在尝试做一些已经在.NET框架中得到很好支持的事情。 Project + Add Reference,选择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方法以了解使用的命令行参数并做出相应的响应。

答案 1 :(得分:1)

如果它可能对您有所帮助,.NET Framework已经提供了Win32互斥对象的包装器。见System.Threading.Mutex。所有主要功能都在那里,包括使用“Global \”等前缀的能力。

答案 2 :(得分:0)

应该像这样简单:

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