如何从.Net调用win32 CreateMutex

Posted

技术标签:

【中文标题】如何从.Net调用win32 CreateMutex【英文标题】:How to call win32 CreateMutex from .Net 【发布时间】:2010-12-26 15:30:55 【问题描述】:

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

【问题讨论】:

嗯。我刚刚删除了 Win32Calls.CreateMutex 的 Win32Calls 部分并直接调用了 CreateMutex ......似乎它可能工作 您使用的是 64 位版本的 Windows 7 吗? .NET Mutex 在 Windows 7 中的工作原理与以前版本基本相同。 这是一个更好的参考...msdn.microsoft.com/en-us/library/… 是的,它是 64 位 Win7 机器... 如果您将平台目标设置为“x86”,.NET 互斥体是否按预期工作?您所看到的也可能是 32/64 位互操作问题(因为您提到了 COM,这只是一个想法)。 【参考方案1】:

它无法编译,因为 CreateMutex 声明不在 Win32Calls 命名空间中。下一个问题是它仍然无法按预期工作,因为 [DllImport] 声明缺少 SetLastError 属性分配。使 Marshal.GetLastWin32Error() 返回错误所必需的。

稍微倒带一下,在 Win7 中使用 Mutex 类应该可以正常工作。我能想到的唯一失败模式是没有在互斥锁名称前加上“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 方法以了解使用了哪些命令行参数并做出相应的响应。

【讨论】:

【参考方案2】:

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

【讨论】:

问题是适用于 XP 和 Vista 的 .Net Mutex,没有被 Windows 7 的非托管程序 (c++) 检测到。在 Windows 7 上,GetLastError() 始终返回 ERROR_SUCCESS 是否互斥存在与否。因此,我试图改变调用互斥锁的方式以适应本地 C++ 代码。注意:.net 互斥体到 .net 在 Windows 7 上运行良好。.Net 互斥体到互操作 c++ 互斥体是失败的......可能在 c++ 方面。 我认为问题不在于互斥锁没有在 Windows 7 中以全球公认的方式创建,因为服务正在创建它。我已将“Global\”附加到互斥锁名称中,因为有些帖子表明对他们有用。但是,这对我也不起作用。 (服务创建的互斥锁不会出现在 ProcessExplorer 查找句柄中,但我知道它在那里,因为如果我运行相同的程序,互斥锁就会警告它已经创建。)微软,服务和互斥锁怎么回事? 在我的测试中,它似乎是一个用户空间的东西。【参考方案3】:

应该很简单:

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://***.com/a/3111740/1644202

【讨论】:

以上是关于如何从.Net调用win32 CreateMutex的主要内容,如果未能解决你的问题,请参考以下文章

如何从 PHP 进行 Win32 API 调用?

如何从使用 .NET 在 win32 下创建的二进制文件中读取 n 个字符?

C#调用Win32 api学习总结

python可以直接调用win32的api吗

从电子邮件正文调用 Win32 应用程序

Win32环境下从ntdll.dll调用Nt函数,C++