Mutex not working as expected

G

Guest

I need to be certain my application only runs once on a machine, and I
implemented a solution using Mutex. The solution was posted many times, but
one great link I found is
http://www.yoda.arachsys.com/csharp/faq/#one.application.instance

The problem is, when I switch users (XP Professional) the second user can
open a second instance of the application! How can I prevent this?

Here's the relevant part of my code:

Sub Main()
Dim vBool As Boolean
Dim FirstInstance As New Mutex(False, "UniqueMutexName", vBool)
If Not vBool Then
Post message to user and exit.
End If
 
C

Chris Calzaretta

This code will only allow you to have 1 instqance of your appliccation
running

If
(UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName))
MsgBox("Cannot start more than one copy of thisgram",
MsgBoxStyle.Exclamation)
Me.Close()
End If
 
H

Herfried K. Wagner [MVP]

Chris,

Chris Calzaretta said:
This code will only allow you to have 1 instqance of your appliccation
running

If
(UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName))
MsgBox("Cannot start more than one copy of thisgram",
MsgBoxStyle.Exclamation)
Me.Close()

This code will fail if there is more than one application with the same
process name. Process names are not necessarily unque.
 
C

Chris Calzaretta

that is correct the code will fail if there is more then 1 process named the
same.
Have you even seen a process that has been named the same. I have not.
If you know a better way of doing this then let me know.

the point of the code is to not allow the same proccess name to be started.
So the code is not failing
It is working how it was designed

way to fix it if your looking for a process name
is
(UBound(Diagnostics.Process.GetProcessesByName(YOUR PROCESS NAME))






Chris
 
G

Guest

Tom,
Mutex's are global to the system unless you specify the Local\\ prefix
to the name... Are you sure that the mutex isn't getting GC'd? I came
Is this true?

Reading CreateMutex (I believe the underlying API used).

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createmutex.asp

http://msdn.microsoft.com/library/d...ermserv/TermServ/kernel_object_namespaces.asp

I get the impression it is true on server side (Server OS) for server
software, however client side (XP Pro) its the opposite... & server side,
client software (as in a Terminal Server Session) its true...


I started looking at this, but did not make any progress:

I was using 2 accounts, one Admin & one User under Windows XP Pro SP2
(VS.NET 2003 .NET 1.1 SP1)

Public Sub Main()
Dim vBool As Boolean
Dim FirstInstance As New Mutex(False, "Local\UniqueMutexName",
vBool)
If Not vBool Then
MessageBox.Show("Already running!", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Else
MessageBox.Show("I'm first", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub


When using "Local\UniqueMutexName" or "UniqueMutexName" shows "I'm first" in
both sessions.

While "Global\UniqueMutexName" causes an exception in the 2nd session (the
User session), The admin session (the first session worked). I suspect the
2nd session is failing because they don't have some Win32 priviledge.

I have not tried my Windows 2003 machine.

Unfortunately I have not got much further on researching this...

I was going to send a not to Jon Skeet, however I haven't tracked down his
email address yet...

Jay
 
T

Tom Shelton

I need to be certain my application only runs once on a machine, and I
implemented a solution using Mutex. The solution was posted many times, but
one great link I found is
http://www.yoda.arachsys.com/csharp/faq/#one.application.instance

The problem is, when I switch users (XP Professional) the second user can
open a second instance of the application! How can I prevent this?

Here's the relevant part of my code:

Sub Main()
Dim vBool As Boolean
Dim FirstInstance As New Mutex(False, "UniqueMutexName", vBool)
If Not vBool Then
Post message to user and exit.
End If

Mutex's are global to the system unless you specify the Local\\ prefix
to the name... Are you sure that the mutex isn't getting GC'd? I came
across this not to long ago. You should probably store the Mutex
instance in a module level or shared variable to make sure that the
reference is not collected during the life of the first instance...

Private firstInstance As Mutext

Public Shared Sub Main ()
Dim first As Boolean
firstInstance = New Mutex (....)
If Not First Then
...
Return
End If
End Sub

Just a thought...
 
J

Jay B. Harlow [MVP - Outlook]

Tom,
Mutex's are global to the system unless you specify the Local\\ prefix
to the name... Are you sure that the mutex isn't getting GC'd? I came
Is this true?

Reading CreateMutex (I believe the underlying API used).

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createmutex.asp

http://msdn.microsoft.com/library/d...ermserv/TermServ/kernel_object_namespaces.asp

I get the impression it is true on server side (Server OS) for server
software, however client side (XP Pro) its the opposite... & server side,
client software (as in a Terminal Server Session) its true...


I started looking at this, but did not make any progress:

I was using 2 accounts, one Admin & one User under Windows XP Pro SP2
(VS.NET 2003 .NET 1.1 SP1)

Public Sub Main()
Dim vBool As Boolean
Dim FirstInstance As New Mutex(False, "Local\UniqueMutexName",
vBool)
If Not vBool Then
MessageBox.Show("Already running!", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Else
MessageBox.Show("I'm first", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub


When using "Local\UniqueMutexName" or "UniqueMutexName" shows "I'm first" in
both sessions.

While "Global\UniqueMutexName" causes an exception in the 2nd session (the
User session), The admin session (the first session worked). I suspect the
2nd session is failing because they don't have some Win32 priviledge.

I have not tried my Windows 2003 machine.

Unfortunately I have not got much further on researching this...

I was going to send a not to Jon Skeet, however I haven't tracked down his
email address yet...

Jay
 
T

Tom Shelton

Tom,
Is this true?

Reading CreateMutex (I believe the underlying API used).

htttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createmutex.asp

http://msdn.microsoft.com/library/d...ermserv/TermServ/kernel_object_namespaces.asp

I get the impression it is true on server side (Server OS) for server
software, however client side (XP Pro) its the opposite... & server side,
client software (as in a Terminal Server Session) its true...

On previous windows versions, there was no fast user switching, so you
wouldn't have more then one user running programs at the same time...
According to the above, fast user switching is implemented as terminal
service sessions. So, the Global\Local prefixes should apply on windows
xp when you change sessions. I think the default is Global though,
since we had to modify an app recently that used this technique -
specifically because of Terminal Services. Our client was using it and
they could only start one instance of the application for the entire
system...

Hmm... Maybe the default changes with the OS. I just always assumed
that they were global on all systems. I might need to run a little
test.
 
J

Jay B. Harlow [MVP - Outlook]

Tom,
According to the above, fast user switching is implemented as terminal
service sessions. So, the Global\Local prefixes should apply on windows Agree!

Hmm... Maybe the default changes with the OS. I just always assumed
that they were global on all systems. I might need to run a little
test.
That's my concern, I was going to run some more tests, either tonight or in
the morning.

Thanks
Jay
 
J

Jay B. Harlow [MVP - Outlook]

Tom,
Ok, ran a couple of tests.

Under Win XP Pro SP2, if you use the Global\ prefix the first one in (Admin
or User) gets the Mutex, the second one gets an ApplicationException with
"Access Is Denied" as the message. Using the Local\ prefix or no prefix they
both get in.

I'm curious if this is a feature of XP, of XP Pro, or of SP2.

Its really annoying that it appears that Terminal Server itself follows one
set of rules, while XP Pro follows another, I wonder what XP Home does... I
wonder what the other servers do (with Remote Desktop)...

The other (more annoying) thing is reading the help I would not expect the
exception I am getting. I would expect a Mutex with vBool = false...

Test code I was using:

Const name As String = "Global\UniqueMutexName"
Try
Dim vBool As Boolean
Dim FirstInstance As New Mutex(False, name, vBool)
If Not vBool Then
MessageBox.Show("Already running!", name,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Else
MessageBox.Show("I'm first", name, MessageBoxButtons.OK,
MessageBoxIcon.Information)
End If
Catch ex As Exception
MessageBox.Show(ex.ToString(), ex.GetType().ToString(),
MessageBoxButtons.OK, MessageBoxIcon.Stop)
End Try

Later
Jay
 
T

Tom Shelton

Tom,
Ok, ran a couple of tests.

Me too...
Under Win XP Pro SP2, if you use the Global\ prefix the first one in (Admin
or User) gets the Mutex, the second one gets an ApplicationException with
"Access Is Denied" as the message. Using the Local\ prefix or no prefix they
both get in.

I'm getting the same result for XP Pro SP2. Both accounts have admin
privledges, so I'm not sure why the error is being raised
I'm curious if this is a feature of XP, of XP Pro, or of SP2.

Good question... I have a XP Pro box at work that is only XP SP1 I
could test this on tommorow.
Its really annoying that it appears that Terminal Server itself follows one
set of rules, while XP Pro follows another, I wonder what XP Home does... I
wonder what the other servers do (with Remote Desktop)...

It does seem rather inconsistant. Especially since fast user switching
is supposed to be terminal services sessions.
The other (more annoying) thing is reading the help I would not expect the
exception I am getting. I would expect a Mutex with vBool = false...

I was thinking the same thing...
 
J

Jay B. Harlow [MVP - Outlook]

mfdatsw1,
I'm submitting something to MS to see what they have to say. I will report
back if I hear anything.

Jay
 
J

Jay B. Harlow [MVP - Outlook]

Trish,
Right now the "solution" is to use a Try/Catch as the discussion between Tom
& I suggests.

I have not heard any thing from MS on the problem.

Hope this helps
Jay
 
T

Trish G

See: http://weblogs.asp.net/whaggard/archive/2003/05/21/7401.aspx

public static void Main(string[] args)
{
// bool used to determine if we created a new mutex
bool createdNew;

// give a unique name for the mutex,
// prefix it with Local\ to ensure that it's created in
//the per-session namespace, not the global namespace.
// Prefix with Global\ if that is what is desired
string mutexName = @"Local\" +
System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

// Create a new mutex object with given name
Mutex m = new Mutex(true, mutexName, out createdNew);

// If the mutex already exists then don't start program becase
// another instance is already running.
if(!createdNew)
return;

//
// Do work like Application.Run(new MainForm());
//

// Release the mutex resources
m.ReleaseMutex();
}
 
G

Guest

This code will also fail if the user is not administrator on their own
machine.
This code will also fail if the user is not administrator on their own
machine.
This code will also fail if the user is not administrator on their own
machine.
This code will also fail if the user is not administrator on their own
machine.
This code will also fail if the user is not administrator on their own
machine.



Chris Calzaretta said:
that is correct the code will fail if there is more then 1 process named the
same.
Have you even seen a process that has been named the same. I have not.
If you know a better way of doing this then let me know.

the point of the code is to not allow the same proccess name to be started.
So the code is not failing
It is working how it was designed

way to fix it if your looking for a process name
is
(UBound(Diagnostics.Process.GetProcessesByName(YOUR PROCESS NAME))






Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top