Furthermore, there didn't seem to be a way to inform the running application that another instance was attempted, so I wrote this function.
Code: Select all
Procedure GetThreadOfCloneProcess()
Protected hp=CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS,0)
If hp
Protected p.PROCESSENTRY32
Protected fnp${100},fnm${100},fp${1000}
p\dwSize=SizeOf(PROCESSENTRY32)
If Process32First_(hp,@p)
Repeat
fnp$=PeekS(@p\szExeFile[0])
If p\th32ProcessID<>GetCurrentProcessId_() And fnp$=GetFilePart(ProgramFilename())
Protected hm=CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE,p\th32ProcessID)
If hm
Protected m.MODULEENTRY32
m\dwSize=SizeOf(MODULEENTRY32)
If Module32First_(hm,@m)
Repeat
fnm$=PeekS(@m\szModule[0],100)
fp$=PeekS(@m\szExePath[0],1000)
If fnm$=GetFilePart(ProgramFilename())
Protected ht=CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD,p\th32ProcessID)
If ht
Protected t.THREADENTRY32
t\dwSize=SizeOf(THREADENTRY32)
If Thread32First_(ht,@t)
Repeat
If t\th32OwnerProcessID=p\th32ProcessID And t\th32ThreadID<>GetCurrentThreadId_()
If SHA1FileFingerprint(ProgramFilename())=SHA1FileFingerprint(fp$)
CloseHandle_(ht)
CloseHandle_(hm)
CloseHandle_(hp)
ProcedureReturn t\th32ThreadID
EndIf
EndIf
Until Not Thread32Next_(ht,@t)
EndIf
CloseHandle_(ht)
EndIf
EndIf
Until Not Module32Next_(hm,@m)
EndIf
CloseHandle_(hm)
EndIf
EndIf
Until Not Process32Next_(hp,@p)
EndIf
CloseHandle_(hp)
EndIf
EndProcedure
It only returns the first thread it comes across, I am assuming that if processes are closed after encountering a duplicate running process, there will only ever be one match in any case.
Usage:
Code: Select all
Global WM_NEW_INSTANCE=RegisterWindowMessage_(@"UNIQUESTRING"),t.l,INITMSG.MSG
PeekMessage_(@INITMSG,#Null,0,0,#PM_NOREMOVE)
t=GetThreadOfCloneProcess()
If t
PostThreadMessage_(t,WM_NEW_INSTANCE,0,0)
End
EndIf
Repeat
If PeekMessage_(@INITMSG,#Null,0,0,#PM_REMOVE)
If INITMSG\message=WM_NEW_INSTANCE
MessageRequester("Oops","I'm running")
EndIf
EndIf
Forever
Quite useful if you have an app in the tray, and you need it to pop up when you attempt to run it from a shortcut, etc.