Windows Single Copy Flag

Is there anything like this in Xojo? Double clicking a file from the app opens a new instance every time and this does not make sense for how this particular application is built. I’ve looked all around Xojo, searched, and can’t seem to find anything about this.

Thanks,
James

Windows does this by default
But you can override that behavior with a mutex
The example on the language reference page stops multiple version from running
http://documentation.xojo.com/index.php/Mutex

I’d swear there is an example somewhere of making it so the new copy tells the already running one about the new document to be opened but I can’t seem to locate it right now

[quote=86292:@James Holy]Is there anything like this in Xojo? Double clicking a file from the app opens a new instance every time and this does not make sense for how this particular application is built. I’ve looked all around Xojo, searched, and can’t seem to find anything about this.
[/quote]

Here is how to do it in your app open process :

  • Do a shell “Tasklist”
  • In the result, use Instr() to find the name of your app executable (for instance “myapp.exe”)

If you do not find “myapp.exe”, then it is OK. If you find “myapp.exe”, the app is already running ; take appropriate action.

I have been using the tasklist command, so I did not think about Mutex. The advantage of Tasklist is that you can also list other applications and even terminate one using tkill.

The sendkeys() method could be used to send keyboards events to the running program.

See https://forum.xojo.com/6009-sendkey-function

What is tricky, though, is that Windows sends keys by the title of the open window. If you have dynamic titles or several windows open, then you have to manage that…

SendKeys won’t necessarily work right

Usually the currently running instance has an ilc socket that a new instance can connect to and the new one sends a “open this document” command to the already running one then it quits so the document that was clicked on still gets opened in the already running instance

Thanks for the replies so far. I do have dynamic titles. This appears to be more complicated than it should be!

I’ll take a peak and see if MBS has any functions that can help with the opendoc on the running instance.

Norm, if you can find that code, I would appreciate it.

Turns out Aaron wrote about it years ago and its in his book
Page 59 Single-Instance Applications Using a Mutex
A quick google for it doesn’t reveal that it available anywhere but I know its in his book on xojolibrary.com

This can probably be done through IPCSocket http://documentation.xojo.com/index.php/IPCSocket if the application is set for it.

I just played with the example project/Communication/IPCSocket.xojo_binary_project

Build it, run the built, then run the project in the IDE. Click Listen on one copy . When you click Connect on the other, you can send messages back and forth.

I imagine transmitting the document to open can be done this way (pseudo code) :

[code]Upon launch ;
if mutex.tryenter
start listen
do your stuff
if IPCSocket.Datavailable then look for document to open
receive connect, then document to open.
When second app closes this generates error 102, close IPCSocket, then open and listen again.

if not mutex.tryenter
connect
send document to open information. Maybe shellpath ?
display the message “cannot run two copies”
close Mutex
quit
this send to first app an error 102 code, so it can close IPCSocket and start listening again
[/code]

From what I see, copy/paste from the example should work.

For windows you could also use WMI with OLEObject.

  // This example will display windows searched process image name
  //http://library.wmifun.net/cimv2/win32_process.html
  
  //http://msdn.microsoft.com/en-us/library/aa394372%28v=vs.85%29.aspx
  
  Dim locator, objWMIService, objs, objProperty  As OLEOBJECT
  Dim nobjs as Integer
  Dim myApp As String
  
  myApp = "myApp.exe"   // Here the name of your app you want to check if running
  
  //  Connect to WMI
  locator = new oleObject("WbemScripting.SWbemlocator", true)
  
  Dim wmiServiceParams(2) as variant
  wmiServiceParams(1) = "."
  wmiServiceParams(2) = "root\\cimv2"
  
  objWMIService= locator.invoke("ConnectServer", wmiServiceParams)
  
  // Run the WMI query
  objs = objWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE Name = '"+myApp+"' ")
  
  If objs.count > 0 Then   // Check if application myApp is running
    nobjs = objs.count - 1
    
    For i as integer = 0 to nobjs
      Dim stringData As String
      
      objProperty = objs.ItemIndex(nobjs)
      // ItemIndex() is not supported in Windows XP only from Windows Vista and upwards
      
      stringData = "CommadnLine: "  + objProperty.Value("CommandLine") + EndOfLine
      stringData = stringData + "Name: "  + objProperty.Value("Name") + EndOfLine
      msgbox stringData
    Next
  Else
    
    Msgbox "No application with name: "+myApp+ " is running"
    
  End if
  
  locator = Nil
  
exception err as oleexception
  msgbox err.message

Aarons code in the book leverages an IPC socket

That is what I thought :slight_smile:

I have aaron’s book somewhere. I just have to find it now. it is probably boxed up somewhere…
might be easier to find a new copy then it is to find my copy.

thanks all!

In Mac OS X there maybe another way than Inter Process Communication :

The second copy can execute AppleScript via an osascript shell to tell the first copy to open the document, then quit.

[quote=89925:@Michel Bujardet]In Mac OS X there maybe another way than Inter Process Communication :

The second copy can execute AppleScript via an osascript shell to tell the first copy to open the document, then quit.[/quote]

You don’t need this on OS X as it behaves this way by default and you have to actually work hard to make it launch a second copy

Then IPC it is for Windows and Linux. It works real well :slight_smile:

So I created an IPCsocket class and initialized it in the open event of app; then I tried to follow the suggestions above, but after writing myIPC.listen and myIPC.connect and launching a file related with the app itself, I always get the “You are not allowed to run multiple instances of the same app” message. Yet, the socket.dataavailable (msgbox me.readall) never shows me anything.
Does anybody have working code?
BTW: using Mutex.
Thanks,
Carlo