Mutex and messages

M

Mark Rae

Hi,

I have a WinForms desktop MDI application written in C#. Following advice
from others in this forum, I prevent multiple instances of the app running
at the same time by creating / trying to create a mutex, as follows:

bool blnCreatedMutex;
objMutex = new System.Threading.Mutex(true, "zzzzzzMyCoolAppzzzzz", out
blnCreatedMutex);
if (!blnCreatedMutex)
{
MessageBox.Show("My Cool App is already running", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Stop);
this.Close();
return;
}

The app saves data files onto the file system, and I have associated these
files' extension with the app's executable. All is well - I interrogate the
args property when the app loads and try to open any files found there e.g.

foreach (string strArg in astrArgs)
{
openFile(strArg);
}

No doubt you can all guess the next question... :) if the app is already
running, and the user double-clicks one of its files, I want to somehow get
a message to it to open the file(s) found in the args of the second
instance, which I will then terminate.

Any assistance gratefully received.

Best,

Mark
 
W

William Stacey [MVP]

Unless I miss an easy solution, this would require some kind of IPC message.
1) User clicks on file ex.
2) New app opens.
3) New app gets file name, and figures out another instance is open.
4) It sends a message to a Named Pipe or Memory mapped file, or file.
5) It also signals a named event that first blocks on in another thread.
6) First app unblocks wait thread and figures out the file name and does
what ever.

I guess you could simplify by using a known hidden file or something. Then
when you get the event, you open and look in the file for file name and path
and do your thing. Other possibilities here. HTH
 
A

Andreas Håkansson

William,

Remoting, Other IPC:s such as mailslots, send message .. <insert
more ideas here>

HTH,

//Andreas
 
M

Mark Rae

Unless I miss an easy solution, this would require some kind of IPC message.

OK.

4) It sends a message to a Named Pipe or Memory mapped file, or file.

That's the bit I'm stuck on...
 
M

Mark Rae

"Andreas Håkansson" <andy.h (at) telia.com> wrote in message

Andreas,
Remoting, Other IPC:s such as mailslots, send message .. <insert more
ideas here>

With the greatest of respect, what does this actually mean...?
 
A

Andreas Håkansson

Mark,

Sorry about that, don't know what got in to me =) Well lets see..
Remoting is the IPC (Inter Process Communication) mechanism which
is shipped with the .NET Framrwork. You can look this up in the docs
and see how you can grab and object from an application and call methods
on it (second instance gets object and informs first instance about file).

There are also a number of IPC: methods built in Windows. Names Pipes,
which William mentioned, is one method MailSlots is another. You can find
more information about these at [1]. However these do require you to use
p/Invoke to use

[1]
http://msdn.microsoft.com/library/d...n-us/ipc/base/interprocess_communications.asp

HTH,

//Andreas
 
M

Mark Rae

Sorry about that, don't know what got in to me =) Well lets see..

That's OK... :)
Remoting is the IPC (Inter Process Communication) mechanism which
is shipped with the .NET Framrwork. You can look this up in the docs
and see how you can grab and object from an application and call methods
on it (second instance gets object and informs first instance about file).

Right! That looks promising - I'll investigate Remoting first.
There are also a number of IPC: methods built in Windows. Names Pipes,
which William mentioned, is one method MailSlots is another. You can find
more information about these at [1]. However these do require you to use
p/Invoke to use

I'm quite comfortable using p/Invoke, as my app already includes several API
calls.

Thanks again.

Mark
 
J

Jon Skeet [C# MVP]

No doubt you can all guess the next question... :) if the app is already
running, and the user double-clicks one of its files, I want to somehow get
a message to it to open the file(s) found in the args of the second
instance, which I will then terminate.

One alternative here is to open a listening socket (on the loopback
adapter) and let that act as the mutex and the communication mechanism.
Only one instance of the app will be able to bind to the port as a
listener, so further instances will fail to bind but could then connect
*to* the port and tell the listener what file to open.
 
M

Mark Rae

Jon,
One alternative here is to open a listening socket (on the loopback
adapter) and let that act as the mutex and the communication mechanism.
Only one instance of the app will be able to bind to the port as a
listener, so further instances will fail to bind but could then connect
*to* the port and tell the listener what file to open.

Sounds like a fabulous idea, and precisely what I'm looking for! If only I
knew how...

BTW, is this such an *unusual* thing to want to do? I'd have thought that,
for anyone writing MDI WinForms apps, it'd be pretty standard stuff. Is this
how e.g. Excel and Word do it...?
 
A

Andreas Håkansson

Mark,

I belive the office applications register them self in the ROT which
would enable you to get a hold of the COM object and invoke calls
on it. Object in the ROT are identified by a moniker.

HTH,

//Andreas
 
J

Jon Skeet [C# MVP]

Mark Rae said:
Sounds like a fabulous idea, and precisely what I'm looking for! If only I
knew how...

Well, start looking at the docs for TcpListener and TcpClient. The rest
is a simple matter of programming :)

<snip>
 
M

Mark Rae

Jon Skeet said:
Well, start looking at the docs for TcpListener and TcpClient. The rest
is a simple matter of programming :)

Thanks for that - found the following article:
http://www.codeguru.com/Csharp/.NET/net_general/threads/article.php/c4611/
which seems to explain the mechanism well enough.

Question: if I were to use something like, say,

TcpListener listener = new TcpListener(IPAddress.Loopback,8080);

would there be any hardware / OS restrictions on this? I.e. does the user
*have* to have a network card? Will this work on completely stand-alone PCs?
Will this work on every operating system supported by the .NET Framework?

Also, presumably there's nothing to guarantee that another application or
process hasn't already opened port 8080, or whichever one I choose...?
 
J

Jon Skeet [C# MVP]

Mark Rae said:
Thanks for that - found the following article:
http://www.codeguru.com/Csharp/.NET/net_general/threads/article.php/c4611/
which seems to explain the mechanism well enough.

Question: if I were to use something like, say,

TcpListener listener = new TcpListener(IPAddress.Loopback,8080);

would there be any hardware / OS restrictions on this? I.e. does the user
*have* to have a network card? Will this work on completely stand-alone PCs?
Will this work on every operating system supported by the .NET Framework?

Also, presumably there's nothing to guarantee that another application or
process hasn't already opened port 8080, or whichever one I choose...?

I think there *may* be a problem on Windows 98, but I'm not sure. I
don't believe you have to have a network card.

Indeed there's nothing to guarantee that another app won't have opened
whichever port you choose. If you choose something pretty obscure and
"high numbered" (over 40000 say) you should be safe enough. 8080 would
be a pretty bad choice, as various things have that as a default port.
 
M

Mark Rae

I think there *may* be a problem on Windows 98, but I'm not sure.

I think we could probably live with that...
I don't believe you have to have a network card.

So, is support for TCP/IP and the loopback adaptor built-in to the .NET
Framework?
Indeed there's nothing to guarantee that another app won't have opened
whichever port you choose. If you choose something pretty obscure and
"high numbered" (over 40000 say) you should be safe enough. 8080 would
be a pretty bad choice, as various things have that as a default port.

Yes, I realised that 8080 would be bad, and would indeed have chosen a
high-numbered port.

I suppose the only other option which would be guaranteed to work on all
operating systems supported by the .NET Framework would be to create a temp
file in a known directory for every argument passed to the app and set up a
timer to "sniff" this folder at regular intervals. According to the docs,
the FileSystemWatcher won't work on 98 or Me...
 
J

Jon Skeet [C# MVP]

Mark Rae said:
So, is support for TCP/IP and the loopback adaptor built-in to the .NET
Framework?

Well, support for them is in the .NET framework, but I believe anything
after Win98 has loopback adapter support in it anyway.
Yes, I realised that 8080 would be bad, and would indeed have chosen a
high-numbered port.

I suppose the only other option which would be guaranteed to work on all
operating systems supported by the .NET Framework would be to create a temp
file in a known directory for every argument passed to the app and set up a
timer to "sniff" this folder at regular intervals. According to the docs,
the FileSystemWatcher won't work on 98 or Me...

That sounds like a bad idea to me - FileSystemWatcher is pretty
unreliable from all I've heard, and if you're not careful you'll end up
with temporary files around etc.
 
W

William Stacey [MVP]

I would think about memory mapped files (MMF). I think they are supported on
98 and over. Maybe even 95, not sure. Very fast and ~easy to wrap in
classes. Plus you can use the swap file for backing store so you don't need
to pass a file name between apps or even know a file name.
 
M

Mark Rae

I would think about memory mapped files (MMF).

I'll check it out - thanks.
I think they are supported on 98 and over. Maybe even 95, not sure.

Wow! You've got the .NET Framework to install on Win95?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetdep/html/dotnetfxref.asp
Very fast and ~easy to wrap in classes. Plus you can use the swap file
for backing store so you don't need to pass a file name between apps or even
know a file name.

Thanks very much for the tip.
 

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