I've been successfully creating a .net mutex like this: SingleIns = new Mutex(true, AppName); for a while. It works in XP, Vista, but apparently not in Windows7. So I need to make an interop call to a Win32 library so other Com components can identify the mutex. I found the following code, but the Win32Calls. is not found... is there an assembly or reference I need? Thanks in advance,
Found code from: http://www.pinvoke.net/default.aspx/kernel32/CreateMutex.html
using 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 t开发者_运维技巧he main form object instance.
if (form != null) {
form.Dispose();
}
}
}
It doesn't compile because the CreateMutex declaration is not in the Win32Calls namespace. Next problem is that it still won't work as intended because the [DllImport] declaration is missing the SetLastError property assignment. Required to make Marshal.GetLastWin32Error() return the error.
Rewinding a bit, using the Mutex class in Win7 should work without a problem. The only failure mode I can think of is not prefixing the mutex name with "Global\" so the mutex is visible in all sessions. That's a bit remote.
More to the point, you are trying to do something that is already very well supported in the .NET framework. Project + Add Reference, select Microsoft.VisualBasic. Make your Program.cs code look like this:
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);
}
}
}
Bonus goodies with this approach is that it automatically sets the focus to the running instance of your program when the user starts it again. And you can override the OnStartupNextInstance method to know what command line arguments were used and respond accordingly.
In case it might help you, the .NET Framework already provides a wrapper of the Win32 mutex object. See System.Threading.Mutex. All of the major functionality is there, including the ability to use prefixes like "Global\".
Should be as simple as:
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
}
system wide mutex creation - ownership: https://stackoverflow.com/a/3111740/1644202
精彩评论