如何从.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 吗? .NETMutex
在 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的主要内容,如果未能解决你的问题,请参考以下文章