Having a single instance and forwarding document open requests

Hi,

I’m trying to accomplish roughly the same thing as MacOpenFile does on the Mac, but on Windows.

For those unfamiliar, let me explain. I want it so that if someone double-clicks on one of my document files, it will either:

  • If no other copy of the app is running, it will start up the application and open the document.

  • If another copy of the app is running, it will just tell that already-running copy to open the document.

Another way to put it: I’d like to work like Visual Studio works on Windows: opening a .c file from the file explorer doesn’t open a separate copy of visual studio.

I’m using py2exe to create an application from my wxPython code.

Sorry if there’s a simple way to do this, but I’ve been unable to find it.

  • My best idea so far is to use the wx.SingleInstanceChecker. With it, I can prevent the second copy of the app from starting up, but I can’t communicate with it to tell it which documents to open. I could use an out of band communication method (TCP sockets, a file, …), but that seems very kludgy.

  • I saw references elsewhere to using DDE on Windows. Unfortunately, I’m not a DDE expert and there appears to be very little documentation in the context of python. …also, the wxwidgets DDE class doesn’t appear to be supported on wxpython (unless I missed it), so I’d have to mix in win32 calls. Ick.

  • The pydocview stuff looks like it might be usable, though again I don’t see any docs for it (and one piece of sample code that doesn’t quite do what I want).

Thanks!

-Doug

Hi,

I'm trying to accomplish roughly the same thing as MacOpenFile does on the
Mac, but on Windows.

For those unfamiliar, let me explain. I want it so that if someone
double-clicks on one of my document files, it will either:
- If no other copy of the app is running, it will start up the application
and open the document.
- If another copy of the app is running, it will just tell that
already-running copy to open the document.

Another way to put it: I'd like to work like Visual Studio works on Windows:
opening a .c file from the file explorer doesn't open a separate copy of
visual studio.

I'm using py2exe to create an application from my wxPython code.

Sorry if there's a simple way to do this, but I've been unable to find it.

* My best idea so far is to use the wx.SingleInstanceChecker. With it, I
can prevent the second copy of the app from starting up, but I can't
communicate with it to tell it which documents to open. I could use an out
of band communication method (TCP sockets, a file, ...), but that seems very
kludgy.

It is kludgy, but it's about all you've got in terms of generic, cross
platform IPC.

* I saw references elsewhere to using DDE on Windows. Unfortunately, I'm
not a DDE expert and there appears to be very little documentation in the
context of python. ...also, the wxwidgets DDE class doesn't appear to be
supported on wxpython (unless I missed it), so I'd have to mix in win32
calls. Ick.

I'm not sure why they aren't wrapped, there aren't any comparable
Python libraries available as far as I know.

···

On 9/26/07, Doug Anderson <doug@vitamindinc.com> wrote:

* The pydocview stuff looks like it might be usable, though again I don't
see any docs for it (and one piece of sample code that doesn't quite do what
I want).

Thanks!

-Doug

Chris Mellon wrote:

* I saw references elsewhere to using DDE on Windows. Unfortunately, I'm
not a DDE expert and there appears to be very little documentation in the
context of python. ...also, the wxwidgets DDE class doesn't appear to be
supported on wxpython (unless I missed it), so I'd have to mix in win32
calls. Ick.

I'm not sure why they aren't wrapped, there aren't any comparable
Python libraries available as far as I know.

I'm not sure why I didn't wrap those classes, probably because it is Windows only, and other forms of IPC are so easy and are available with Python. (Like xmlrpc for example.)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

One interesting (aka: weird) way to do this is using tcp/ip, which is
supported on all modern systems. When your App opens, check to see if
another instance has opened a specific port on localhost. If it has,
send the open command across TCP and exit. If it has not, open the
port and listen for incoming open requests. (This is how JEdit handles
the same problem, although I think their backend server takes care of
a little more than just opening files).

The downside is that I have a feeling that under Windows (Vista
especiall), you would get firewall message boxes ("Are you sure you
want to get out of bed this morning?"). Might be something to
experiment with though.

Dusty

···

On 26/09/2007, Doug Anderson <doug@vitamindinc.com> wrote:

Hi,

I'm trying to accomplish roughly the same thing as MacOpenFile does on the
Mac, but on Windows.

For those unfamiliar, let me explain. I want it so that if someone
double-clicks on one of my document files, it will either:
- If no other copy of the app is running, it will start up the application
and open the document.
- If another copy of the app is running, it will just tell that
already-running copy to open the document.

Another way to put it: I'd like to work like Visual Studio works on Windows:
opening a .c file from the file explorer doesn't open a separate copy of
visual studio.

Whoops, maybe I should have finished reading. :wink: I apologize. I
personally disagree about TCP sockets being kludgy. They are fully
supported, completely event driven, and don't take up a lot of
overhead. Since you're connecting to localhost, you can probably get
away with UDP sockets, with even less overhead; its unlikely packets
would be dropped.

Dusty

···

On 26/09/2007, Dusty Phillips <buchuki@gmail.com> wrote:

> For those unfamiliar, let me explain. I want it so that if someone
> double-clicks on one of my document files, it will either:
> - If no other copy of the app is running, it will start up the application
> and open the document.
> - If another copy of the app is running, it will just tell that
> already-running copy to open the document.
>
> Another way to put it: I'd like to work like Visual Studio works on Windows:
> opening a .c file from the file explorer doesn't open a separate copy of
> visual studio.

One interesting (aka: weird) way to do this is using tcp/ip, which is
supported on all modern systems.

> * My best idea so far is to use the wx.SingleInstanceChecker. With it, I

can prevent the second copy of the app from starting up, but I can't

> communicate with it to tell it which documents to open. I could use an out
> of band communication method (TCP sockets, a file, ...), but that seems very
> kludgy.

Thanks for all the quick responses.

I decided against TCP socket, mostly because:
- You've got to pick an arbitrary port and hardcode it. If that port is taken, you are stuck with a really obscure failure case (not common, but I'm paranoid).
- You can't support multi-user systems well (each user should have their own single instance), since their TCP sockets would collide.

I've never used XMLRCP, but my quick glance at it indicates that it suffers from similar problems (correct me if I'm wrong), since it runs on TCP.

I've almost got a system working that uses files. I have a listener thread watching a special directory for the appearance of files, which are used as a form of communication. Not great, but it works even on windows (which doesn't seem to have mkfifo). I figure out the listener thread with the SingleInstanceChecker (the warnings about stale lock files are a bit annoying, though I found a way around that with some google searching).

I guess my "kludgy" comment was more that with all of the advanced features of wxpython elsewhere, it surprised me that I had to jump through so many hoops and make so many design tradeoffs to solve what seemed like a relatively common problem. ...but I know, programming is filled with such things. :wink: WxPython at least makes it so I don't have to jump through as many hoops elsewhere in my code!

-Doug

···

---

On Sep 26, 2007, at 10:23 PM, Dusty Phillips wrote:

On 26/09/2007, Dusty Phillips <buchuki@gmail.com> wrote:

For those unfamiliar, let me explain. I want it so that if someone
double-clicks on one of my document files, it will either:
- If no other copy of the app is running, it will start up the application
and open the document.
- If another copy of the app is running, it will just tell that
already-running copy to open the document.

Another way to put it: I'd like to work like Visual Studio works on Windows:
opening a .c file from the file explorer doesn't open a separate copy of
visual studio.

One interesting (aka: weird) way to do this is using tcp/ip, which is
supported on all modern systems.

* My best idea so far is to use the wx.SingleInstanceChecker. With it, I
can prevent the second copy of the app from starting up, but I can't
communicate with it to tell it which documents to open. I could use an out
of band communication method (TCP sockets, a file, ...), but that seems very
kludgy.

Whoops, maybe I should have finished reading. :wink: I apologize. I
personally disagree about TCP sockets being kludgy. They are fully
supported, completely event driven, and don't take up a lot of
overhead. Since you're connecting to localhost, you can probably get
away with UDP sockets, with even less overhead; its unlikely packets
would be dropped.

Dusty

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Doug Anderson wrote:

Thanks for all the quick responses.

I decided against TCP socket, mostly because:
- You've got to pick an arbitrary port and hardcode it. If that port is taken, you are stuck with a really obscure failure case (not common, but I'm paranoid).

Well, you could use the portmap service (port 111) if it's running. That allows you to register a server at an arbitrary port number and have clients find it by querying the portmapper. This is how RPC-based services work.

- You can't support multi-user systems well (each user should have their own single instance), since their TCP sockets would collide.

Incorrect. The server can have several connections active through a single port number (how do you think Google and Amazon provide the range of services they do)? The uniqueness requirement is on the tuple

   (protocol, local port, local address, remote port, remote address)

You should maybe take a look at the socket how-two.

I've never used XMLRCP, but my quick glance at it indicates that it suffers from similar problems (correct me if I'm wrong), since it runs on TCP.

That was clearly a very quick glance indeed.

I've almost got a system working that uses files. I have a listener thread watching a special directory for the appearance of files, which are used as a form of communication. Not great, but it works even on windows (which doesn't seem to have mkfifo). I figure out the listener thread with the SingleInstanceChecker (the warnings about stale lock files are a bit annoying, though I found a way around that with some google searching).

I guess my "kludgy" comment was more that with all of the advanced features of wxpython elsewhere, it surprised me that I had to jump through so many hoops and make so many design tradeoffs to solve what seemed like a relatively common problem. ...but I know, programming is filled with such things. :wink: WxPython at least makes it so I don't have to jump through as many hoops elsewhere in my code!

Well, if you want to talk about "kludgey", your solution appears kludgey in the extreme. Fortunately the reason for it is ignorance of how TCP sockets actually work, and ignorance (which we all suffer from) is curable.

Perhaps you might take a look at

   http://www.holdenweb.com/linuxworld/index.htm

which has some basic TCP and UDP examples you can play with.

regards
  Steve

···

-Doug

---

On Sep 26, 2007, at 10:23 PM, Dusty Phillips wrote:

On 26/09/2007, Dusty Phillips <buchuki@gmail.com> wrote:

For those unfamiliar, let me explain. I want it so that if someone
double-clicks on one of my document files, it will either:
- If no other copy of the app is running, it will start up the application
and open the document.
- If another copy of the app is running, it will just tell that
already-running copy to open the document.

Another way to put it: I'd like to work like Visual Studio works on Windows:
opening a .c file from the file explorer doesn't open a separate copy of
visual studio.

One interesting (aka: weird) way to do this is using tcp/ip, which is
supported on all modern systems.

* My best idea so far is to use the wx.SingleInstanceChecker. With it, I
can prevent the second copy of the app from starting up, but I can't
communicate with it to tell it which documents to open. I could use an out
of band communication method (TCP sockets, a file, ...), but that seems very
kludgy.

Whoops, maybe I should have finished reading. :wink: I apologize. I
personally disagree about TCP sockets being kludgy. They are fully
supported, completely event driven, and don't take up a lot of
overhead. Since you're connecting to localhost, you can probably get
away with UDP sockets, with even less overhead; its unlikely packets
would be dropped.

Dusty

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden

Sorry, the dog ate my .sigline

For the record (too many times I've seen mailing list archives with
questions but not answers! ;-), this can be easily solved as follows:

Pick an arbitrary open port at startup and store it in a well-known
file location. It can be a different port for each user and isn't
hard-coded.

Dusty

···

On 27/09/2007, Doug Anderson <doug@vitamindinc.com> wrote:

I decided against TCP socket, mostly because:
- You've got to pick an arbitrary port and hardcode it. If that port
is taken, you are stuck with a really obscure failure case (not
common, but I'm paranoid).
- You can't support multi-user systems well (each user should have
their own single instance), since their TCP sockets would collide.

Doug, I’m using DDE with Python, and it works quite well. But I
agree, it’s hard to find relevant documentation.

I’m a crossword constructor, and a charter member of CrosSynergy
Syndicate, one of whose clients, for both online and hard-copy puzzles,
is the Washington Post. To prepare the puzzle images we send off to
the Post’s typesetter, I use Python DDE to invoke Antony Lewis’s
Crossword Compiler
(
www.crosswordcompiler.com
), as it provides all the output
functionality we need, and avoids me having to write a lot more
code. (Crossword Compiler couldn’t do what we needed at first, but
Antony was quite amenable to my suggestions, and redesigned his export
interface to meet our output requirements.)

Here’s what the connect-to code looks like:

`def connect_to_CC():

server = dde.CreateServer()

server.Create("CC_DDE")

print "Invoking Crossword Compiler

…",

os.spawnv(os.P_NOWAIT, CC_EXE, [])

time.sleep(1)

print "Connecting to Crossword Compiler

…",

cc = dde.CreateConversation(server)

try:

cc.ConnectTo(“ccw”,“control”)

ConnectTo(service,topic)

    print

“connected”

except:

    print 'cannot!  Aborting

…’

    time.sleep(5)

    sys.exit(1)

return (server,cc)

`And here’s a partial look at how I talk to Crossword
Compiler:

` (server,cc) = connect_to_CC()

 puz_spec = os.path.join(PUZ_DIR,

puz_fnm)

 open_cmd = '[Open("' + puz_spec +

‘",“WashPost”)]’

 cc.Exec(open_cmd)

 fo_spec = os.path.join(OUT_DIR, fo_fnm)

 print 'Creating    empty grid

file’, fo_spec, ‘…’,

 export_cmd =

‘[Export(“WP-eps-puz”,"’ + fo_spec + ‘")]’

 cc.Exec(export_cmd)

 fo_spec = os.path.join(OUT_DIR, fo_fnm)

 print 'Creating solution grid file', fo_spec,

‘…’,

 export_cmd =

‘[Export(“WP-eps-sol”,"’ + fo_spec + ‘")]’

 cc.Exec(export_cmd)

 cc.Exec('[Close()]')

 server.Shutdown()

 server.Destroy()

`I hope this helps. Yes, you do need an “import win32ui,
dde” statement, and I certainly understand your “Ick”
comment, but I think you’ll agree that there’s none of win32ui’s
“icky” stuff in the code above.

My apologies, if needed, to the group here, since, while this note is in
response to a question posed here, it does not involve wxPython.

Bob

···

At 04:58 PM 9/26/2007, Doug Anderson wrote:

  • I saw references elsewhere to
    using DDE on Windows. Unfortunately, I’m not a DDE expert and there
    appears to be very little documentation in the context of python.
    …also, the wxwidgets DDE class doesn’t appear to be supported on
    wxpython (unless I missed it), so I’d have to mix in win32 calls.
    Ick.

Steve,

Thanks for your answers, but I don't think they are particularly useful in my case.

* Specifically, I am trying to support Windows, which doesn't have portmap on 111 (at least, not on my Windows box). ...and yes, I know Windows is a pain in the butt sometimes, but I still need to support it.

* Yes, you can have multiple TCP connections through a single port number. I have spent quite a bit of time with TCP/IP. ...but I don't think you're understanding my usage model. I'm writing a GUI app. What does that mean? Let's think through it on Windows (Mac and Unix have similar concepts, and yes I know that Unix came up with it first). We'll choose port 12356, as an example. If you log in with the user Steve and start up the app, it will now listen on port 12356. Now, I leave user Steve logged in and log in with user Doug. Now, the user Doug tries to start the GUI app. If I don't choose a different port, Steve's program will get my TCP requests.

* Yes, my XMLRPC glance was very quick. I will admit that. If you think I should give it another glance (now that you understand my usage), I will.

* <Sigh> Sadly, ignorance is contagious. I will admit that I have a pretty bad strain of it, but I am at least trying to get better. :wink:

-Doug

···

---

On Sep 27, 2007, at 11:02 AM, Steve Holden wrote:

Doug Anderson wrote:

Thanks for all the quick responses.
I decided against TCP socket, mostly because:
- You've got to pick an arbitrary port and hardcode it. If that port is taken, you are stuck with a really obscure failure case (not common, but I'm paranoid).

Well, you could use the portmap service (port 111) if it's running. That allows you to register a server at an arbitrary port number and have clients find it by querying the portmapper. This is how RPC-based services work.

- You can't support multi-user systems well (each user should have their own single instance), since their TCP sockets would collide.

Incorrect. The server can have several connections active through a single port number (how do you think Google and Amazon provide the range of services they do)? The uniqueness requirement is on the tuple

  (protocol, local port, local address, remote port, remote address)

You should maybe take a look at the socket how-two.

I've never used XMLRCP, but my quick glance at it indicates that it suffers from similar problems (correct me if I'm wrong), since it runs on TCP.

That was clearly a very quick glance indeed.

I've almost got a system working that uses files. I have a listener thread watching a special directory for the appearance of files, which are used as a form of communication. Not great, but it works even on windows (which doesn't seem to have mkfifo). I figure out the listener thread with the SingleInstanceChecker (the warnings about stale lock files are a bit annoying, though I found a way around that with some google searching).
I guess my "kludgy" comment was more that with all of the advanced features of wxpython elsewhere, it surprised me that I had to jump through so many hoops and make so many design tradeoffs to solve what seemed like a relatively common problem. ...but I know, programming is filled with such things. :wink: WxPython at least makes it so I don't have to jump through as many hoops elsewhere in my code!

Well, if you want to talk about "kludgey", your solution appears kludgey in the extreme. Fortunately the reason for it is ignorance of how TCP sockets actually work, and ignorance (which we all suffer from) is curable.

Perhaps you might take a look at

  http://www.holdenweb.com/linuxworld/index.htm

which has some basic TCP and UDP examples you can play with.

regards
Steve

-Doug
---
On Sep 26, 2007, at 10:23 PM, Dusty Phillips wrote:

On 26/09/2007, Dusty Phillips <buchuki@gmail.com> wrote:

For those unfamiliar, let me explain. I want it so that if someone
double-clicks on one of my document files, it will either:
- If no other copy of the app is running, it will start up the application
and open the document.
- If another copy of the app is running, it will just tell that
already-running copy to open the document.

Another way to put it: I'd like to work like Visual Studio works on Windows:
opening a .c file from the file explorer doesn't open a separate copy of
visual studio.

One interesting (aka: weird) way to do this is using tcp/ip, which is
supported on all modern systems.

* My best idea so far is to use the wx.SingleInstanceChecker. With it, I
can prevent the second copy of the app from starting up, but I can't
communicate with it to tell it which documents to open. I could use an out
of band communication method (TCP sockets, a file, ...), but that seems very
kludgy.

Whoops, maybe I should have finished reading. :wink: I apologize. I
personally disagree about TCP sockets being kludgy. They are fully
supported, completely event driven, and don't take up a lot of
overhead. Since you're connecting to localhost, you can probably get
away with UDP sockets, with even less overhead; its unlikely packets
would be dropped.

Dusty

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden

Sorry, the dog ate my .sigline

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

I suggest using named pipes, rather than TCP. This should work in Windows, too.

···

On 9/27/07, Doug Anderson <doug@vitamindinc.com> wrote:

Steve,

Thanks for your answers, but I don't think they are particularly
useful in my case.

* Specifically, I am trying to support Windows, which doesn't have
portmap on 111 (at least, not on my Windows box). ...and yes, I know
Windows is a pain in the butt sometimes, but I still need to support it.

* Yes, you can have multiple TCP connections through a single port
number. I have spent quite a bit of time with TCP/IP. ...but I
don't think you're understanding my usage model. I'm writing a GUI
app. What does that mean? Let's think through it on Windows (Mac
and Unix have similar concepts, and yes I know that Unix came up with
it first). We'll choose port 12356, as an example. If you log in
with the user Steve and start up the app, it will now listen on port
12356. Now, I leave user Steve logged in and log in with user Doug.
Now, the user Doug tries to start the GUI app. If I don't choose a
different port, Steve's program will get my TCP requests.

* Yes, my XMLRPC glance was very quick. I will admit that. If you
think I should give it another glance (now that you understand my
usage), I will.

* <Sigh> Sadly, ignorance is contagious. I will admit that I have a
pretty bad strain of it, but I am at least trying to get better. :wink:

-Doug

Dusty,

Thanks for the followup! Yeah, it bugs me when I find a question that's the exact same as mine (and with no answers) posted.

Your solution is probably the best one. I remember thinking about it, but for some reason dismissed it. I figured that since I was already using the filesystem for some communication (about the port number), I might as well just go whole hog and use the filesystem for all my communication. My solution (using the filesystem for all communication) worked, but I bet the TCP method would be just a hair more reliable (and more efficient, since I couldn't find a way to efficiently block on a file being created).

BTW: for the person reading the archives, picking a "well-known" file location should involve the use of:
  wx.StandardPaths.Get().GetUserLocalDataDir()

-Doug

···

---

On Sep 27, 2007, at 11:05 AM, Dusty Phillips wrote:

On 27/09/2007, Doug Anderson <doug@vitamindinc.com> wrote:

I decided against TCP socket, mostly because:
- You've got to pick an arbitrary port and hardcode it. If that port
is taken, you are stuck with a really obscure failure case (not
common, but I'm paranoid).
- You can't support multi-user systems well (each user should have
their own single instance), since their TCP sockets would collide.

For the record (too many times I've seen mailing list archives with
questions but not answers! ;-), this can be easily solved as follows:

Pick an arbitrary open port at startup and store it in a well-known
file location. It can be a different port for each user and isn't
hard-coded.

Dusty

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Chris,

The following is in my python manual (which made me give up on named pipes, which would have been perfect). Specifically, the “Availability” section turned me off to it, since it didn’t include Windows:

mkfifo(path[, mode ])

Create a FIFO (a named pipe) named path with numeric mode mode. The default mode is 0666 (octal). The

current umask value is first masked out from the mode. Availability: Macintosh, UNI X.

FIFOs are pipes that can be accessed like regular files. FIFOs exist until they are deleted (for example with

os.unlink()). Generally, FIFOs are used as rendezvous between “client” and “server” type processes: the

server opens the FIFO for reading, and the client opens it for writing. Note that mkfifo() doesn’t open the

FIFO — it just creates the rendezvous point.

-Doug

···

On Sep 27, 2007, at 11:23 AM, Chris Mellon wrote:

On 9/27/07, Doug Anderson doug@vitamindinc.com wrote:

Steve,

Thanks for your answers, but I don’t think they are particularly

useful in my case.

  • Specifically, I am trying to support Windows, which doesn’t have

portmap on 111 (at least, not on my Windows box). …and yes, I know

Windows is a pain in the butt sometimes, but I still need to support it.

  • Yes, you can have multiple TCP connections through a single port

number. I have spent quite a bit of time with TCP/IP. …but I

don’t think you’re understanding my usage model. I’m writing a GUI

app. What does that mean? Let’s think through it on Windows (Mac

and Unix have similar concepts, and yes I know that Unix came up with

it first). We’ll choose port 12356, as an example. If you log in

with the user Steve and start up the app, it will now listen on port

  1. Now, I leave user Steve logged in and log in with user Doug.

Now, the user Doug tries to start the GUI app. If I don’t choose a

different port, Steve’s program will get my TCP requests.

  • Yes, my XMLRPC glance was very quick. I will admit that. If you

think I should give it another glance (now that you understand my

usage), I will.

  • Sadly, ignorance is contagious. I will admit that I have a

pretty bad strain of it, but I am at least trying to get better. :wink:

-Doug

I suggest using named pipes, rather than TCP. This should work in Windows, too.


To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org

For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

  • Yes, you can have multiple TCP connections through a single port
    number. I have spent quite a bit of time with TCP/IP. …but I

don’t think you’re understanding my usage model. I’m writing a GUI
app. What does that mean? Let’s think through it on Windows (Mac
and Unix have similar concepts, and yes I know that Unix came up with

it first). We’ll choose port 12356, as an example. If you log in
with the user Steve and start up the app, it will now listen on port
12356. Now, I leave user Steve logged in and log in with user Doug.

Now, the user Doug tries to start the GUI app. If I don’t choose a
different port, Steve’s program will get my TCP requests.

This is really easy to get around; as Steve said, just generate a random

port on startup and store it in a well-known location. We do this here for
XML-RPC based IPC on a multi-user (in particular, terminal services/Cisco
environments)

On startup, we call a ‘getPort()’ function. Said funciton looks in mysoftware.cfg,
and sees if there’s a port specified for user ‘bob’ (this username obtained via
os.environ.get(‘USERNAME’, os.environ.get(‘USER’, ‘None’)) approximately).
If there is, we return it. If there isn’t, we generate a new port number half

randomally, save it in the file, and return it.

There’s also a failsafe in that if creating the XML-RPC server goes bad, I
pick a /new/ port and overwrite the old choice; just in case.

You'll have to use the pywin32 package on Windows.

···

On 9/27/07, Doug Anderson <doug@vitamindinc.com> wrote:

Chris,

The following is in my python manual (which made me give up on named pipes,
which would have been perfect). Specifically, the "Availability" section
turned me off to it, since it didn't include Windows:

mkfifo(path[, mode ])
Create a FIFO (a named pipe) named path with numeric mode mode. The default
mode is 0666 (octal). The
current umask value is first masked out from the mode. Availability:
Macintosh, UNI X.
FIFOs are pipes that can be accessed like regular files. FIFOs exist until
they are deleted (for example with
os.unlink()). Generally, FIFOs are used as rendezvous between "client" and
"server" type processes: the
server opens the FIFO for reading, and the client opens it for writing. Note
that mkfifo() doesn't open the
FIFO — it just creates the rendezvous point.

-Doug

Doug Anderson wrote:

Steve,

Thanks for your answers, but I don't think they are particularly useful in my case.

Sorry 'bout that!

* Specifically, I am trying to support Windows, which doesn't have portmap on 111 (at least, not on my Windows box). ...and yes, I know Windows is a pain in the butt sometimes, but I still need to support it.

Right, forget portmapping on Windows (unless you want to support the pain that is Cygwin ... I'd advise against it for this specific purpose).

* Yes, you can have multiple TCP connections through a single port number. I have spent quite a bit of time with TCP/IP. ...but I don't think you're understanding my usage model. I'm writing a GUI app. What does that mean? Let's think through it on Windows (Mac and Unix have similar concepts, and yes I know that Unix came up with it first). We'll choose port 12356, as an example. If you log in with the user Steve and start up the app, it will now listen on port 12356. Now, I leave user Steve logged in and log in with user Doug. Now, the user Doug tries to start the GUI app. If I don't choose a different port, Steve's program will get my TCP requests.

So you are talking a unique "server" process for each user? Presumably this is so that user permissions are specific to the user? You could use impersonation for that ... but you're right, I didn't understand your model that well until I went back to the original post.

* Yes, my XMLRPC glance was very quick. I will admit that. If you think I should give it another glance (now that you understand my usage), I will.

I don't think XMLRPC is what you want. And DDE almost certainly isn't.

* <Sigh> Sadly, ignorance is contagious. I will admit that I have a pretty bad strain of it, but I am at least trying to get better. :wink:

And communicating well too. I can't think of anything that hasn't already been suggested, sorry.

regards
  Steve

···

--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden

Sorry, the dog ate my .sigline

Doug,

From: Doug Anderson [mailto:doug@vitamindinc.com]
Sent: Wednesday, September 26, 2007 3:58 PM
To: wxPython-users@lists.wxwidgets.org
Subject: Having a single instance and forwarding document
open requests

Hi,

I'm trying to accomplish roughly the same thing as
MacOpenFile does on the Mac, but on Windows.

For those unfamiliar, let me explain. I want it so that if
someone double-clicks on one of my document files, it will either:
- If no other copy of the app is running, it will start up
the application and open the document.
- If another copy of the app is running, it will just tell
that already-running copy to open the document.

Another way to put it: I'd like to work like Visual Studio
works on Windows: opening a .c file from the file explorer
doesn't open a separate copy of visual studio.

I'm using py2exe to create an application from my wxPython code.

Sorry if there's a simple way to do this, but I've been
unable to find it.

* My best idea so far is to use the wx.SingleInstanceChecker.
With it, I can prevent the second copy of the app from
starting up, but I can't communicate with it to tell it which
documents to open. I could use an out of band communication
method (TCP sockets, a file, ...), but that seems very kludgy.

* I saw references elsewhere to using DDE on Windows.
Unfortunately, I'm not a DDE expert and there appears to be
very little documentation in the context of python. ...also,
the wxwidgets DDE class doesn't appear to be supported on
wxpython (unless I missed it), so I'd have to mix in win32
calls. Ick.

* The pydocview stuff looks like it might be usable, though
again I don't see any docs for it (and one piece of sample
code that doesn't quite do what I want).

Thanks!

-Doug

I do this sort of thing with a couple programs I wrote. I check if the
browser is open and if it is, then I check if it's got the web email
client loaded. If not, then I load the program.

I use win32gui calls, which communicates via COM. First I grab a handle of
the application. You'll need something like Spy++ or Winspector to get the
handle name.

<code>

# if the handle fails, open the application
try:
    hwnd = win32gui.FindWindow('SomeHandle',None)

    # force the application to have the focus
    win32gui.SetForegroundWindow(hwnd)

    # get the window's title
    winTitle = win32gui.GetWindowText(win32gui.GetForegroundWindow())
    
    # if the title is correct, you're done. Otherwise, open a new
doc/window
except:
    # open the application

</code>

Something else for your toolbox as I see you have had plenty of other
suggestions.

Mike

···

-----Original Message-----

I've seen code like this in a lot of different places, and it's really
common on 'code factory' style sites, but I'd really encourage you to
not use it. wxSingleInstanceChecker uses a named mutex, which is a
much more reliable mechanism.

···

On 9/27/07, Mike Driscoll <mdriscoll@co.marshall.ia.us> wrote:

Doug,

> -----Original Message-----
> From: Doug Anderson [mailto:doug@vitamindinc.com]
> Sent: Wednesday, September 26, 2007 3:58 PM
> To: wxPython-users@lists.wxwidgets.org
> Subject: Having a single instance and forwarding document
> open requests
>
> Hi,
>
> I'm trying to accomplish roughly the same thing as
> MacOpenFile does on the Mac, but on Windows.
>
> For those unfamiliar, let me explain. I want it so that if
> someone double-clicks on one of my document files, it will either:
> - If no other copy of the app is running, it will start up
> the application and open the document.
> - If another copy of the app is running, it will just tell
> that already-running copy to open the document.
>
> Another way to put it: I'd like to work like Visual Studio
> works on Windows: opening a .c file from the file explorer
> doesn't open a separate copy of visual studio.
>
> I'm using py2exe to create an application from my wxPython code.
>
>
>
> Sorry if there's a simple way to do this, but I've been
> unable to find it.
>
> * My best idea so far is to use the wx.SingleInstanceChecker.
> With it, I can prevent the second copy of the app from
> starting up, but I can't communicate with it to tell it which
> documents to open. I could use an out of band communication
> method (TCP sockets, a file, ...), but that seems very kludgy.
>
> * I saw references elsewhere to using DDE on Windows.
> Unfortunately, I'm not a DDE expert and there appears to be
> very little documentation in the context of python. ...also,
> the wxwidgets DDE class doesn't appear to be supported on
> wxpython (unless I missed it), so I'd have to mix in win32
> calls. Ick.
>
> * The pydocview stuff looks like it might be usable, though
> again I don't see any docs for it (and one piece of sample
> code that doesn't quite do what I want).
>
>
> Thanks!
>
> -Doug
>

I do this sort of thing with a couple programs I wrote. I check if the
browser is open and if it is, then I check if it's got the web email
client loaded. If not, then I load the program.

I use win32gui calls, which communicates via COM. First I grab a handle of
the application. You'll need something like Spy++ or Winspector to get the
handle name.

<code>

# if the handle fails, open the application
try:
    hwnd = win32gui.FindWindow('SomeHandle',None)

    # force the application to have the focus
    win32gui.SetForegroundWindow(hwnd)

    # get the window's title
    winTitle = win32gui.GetWindowText(win32gui.GetForegroundWindow())

    # if the title is correct, you're done. Otherwise, open a new
doc/window
except:
    # open the application

</code>

Something else for your toolbox as I see you have had plenty of other
suggestions.

Mike

>
> I do this sort of thing with a couple programs I wrote. I
check if the
> browser is open and if it is, then I check if it's got the
web email
> client loaded. If not, then I load the program.
>
> I use win32gui calls, which communicates via COM. First I grab a
> handle of the application. You'll need something like Spy++ or
> Winspector to get the handle name.
>
> <code>
>
> # if the handle fails, open the application
> try:
> hwnd = win32gui.FindWindow('SomeHandle',None)
>
> # force the application to have the focus
> win32gui.SetForegroundWindow(hwnd)
>
> # get the window's title
> winTitle =
win32gui.GetWindowText(win32gui.GetForegroundWindow())
>
> # if the title is correct, you're done. Otherwise, open a new
> doc/window
> except:
> # open the application
>
> </code>
>
> Something else for your toolbox as I see you have had
plenty of other
> suggestions.
>
> Mike
>

I've seen code like this in a lot of different places, and
it's really common on 'code factory' style sites, but I'd
really encourage you to not use it. wxSingleInstanceChecker
uses a named mutex, which is a much more reliable mechanism.

Chris,

Does wxSingleInstanceChecker also bring the program to the foreground? I
was using this method for automating Firefox with SendKeys and other hacks
since there isn't a COM method of doing it. I did see something about
being able to embed Python into Firefox somehow by compiling Firefox by
hand, but I didn't want to mess with that.

If I could have found a better way to do this kind of thing, I would have.
Oh well. To each their own.

Mike