Here's a mutex class based on that old Advisor code from 1998, and in
production from then until 2008! There's also an example on calling
it.
One thing to watch out for with all these approaches is fast-user
switching on Windows XP where more than one user can be logged on at
the same time.
--stuart
define class mutex as _line
cFormCaption = ''
hMutex = 0
nMutexError = 0
* credit to George Tasker for the code
* published in FoxPro Advisor, november 1998
procedure init
lparameter lcFormCaption
declare integer CreateMutex in Win32API;
string @lpMutexAttributes,;
string bInitialOwner,;
string @lpName
declare integer GetLastError in Win32API
local cOwner, cName
* replace spaces with empty strings so the Mutex name is
different
* from the caption.
cName = chrtran(lcFormCaption, space(1), '')
* Simulate a BOOL type equaling TRUE.
cOwner = chr(1)
with this
.cFormCaption = lcFormCaption
.hMutex = CreateMutex(0, cOwner, @cName)
.nMutexError = GetLastError()
endwith
return
endproc
* note - I couldn't get George's DisplayInstance to work, so I've
used part of it and some other code..
procedure DisplayInstance
local cWindowName as string, nHWND as integer, nNextHWND as
integer, ;
cBuffer as string, lDummy as Boolean, lIcon as Boolean
cWindowName = this.cFormCaption
* We don't want beautify to mess with ShowWindow (which is a VFP
keyword as well
* as the DLL function name) - see
http://rickschummer.com/blog/2005/03/vfp-9-hidden-gem-beautify-directive.html
* This is a directive instructing Beautify to ignore keywords
(i.e.
ShowWindow)
*# beautify keyword_nochange
declare integer SetForegroundWindow in win32api long lnhWnd
declare integer GetWindowText in win32api integer, string,
integer
declare integer GetWindow in win32api integer,integer
declare integer IsWindowVisible in win32api integer
declare integer GetActiveWindow in win32api
declare short IsIconic in win32API integer hwnd
declare integer ShowWindow in win32API as WIN32_ShowWindow
integer
hwnd, integer nCmdShow
* End beautify directive.
*# beautify
if len(cWindowName) < 1
return
endif
* get the window handle of this window
nHWND = GetActiveWindow()
* get the handle of the first window along
nNextHWND = GetWindow(nHWND,0)
* loop through each window to search the title
do while nNextHWND <> 0
* if window is not this handle and not a child window
if (nNextHWND <> nHWND .and. GetWindow(nNextHWND,4) = 0)
cBuffer = space(64)
* get the window text
lDummy = GetWindowText(nNextHWND,@cBuffer,64)
* if this is the specified window.
if cWindowName $ cBuffer
* Determine if the application
* is minimized (an icon).
lIcon = (IsIconic(nNextHWND) # 0)
if lIcon
* It's an icon, so restore it
=WIN32_ShowWindow(nNextHWND, 9)
endif
=SetForegroundWindow(nNextHWND)
exit
endif
endif
nNextHWND = GetWindow(nNextHWND, 2)
enddo
endproc
procedure destroy
declare integer WaitForSingleObject in Win32API;
integer hObject, integer dwTimeOut
declare short ReleaseMutex in Win32API;
integer hMutex
declare short CloseHandle in Win32API;
integer hObject
local nResult
if this.hMutex # 0
nResult = WaitForSingleObject(this.hMutex, 50)
* 258 = STATUS_TIMEOUT
if nResult # 258
nResult = ReleaseMutex(this.hMutex)
* 1 equals Boolean TRUE
if nResult = 1
nResult = CloseHandle(this.hMutex)
endif
endif
endif
return
endproc
enddefine
This is a procedure designed to be called from an application class.
Note that the mutex handle returned must be stored so it can be
released when the app exits.
I can't remember why I implemented the property, must have been a reason though.
procedure CreateAppMutex
* Returns True if this is the only instance, otherwise attempts
to display
* the existing instance and returns False.
local cName, cProperty, nHwnd, lOnlyInstance, nNextHWND, lIcon
* Use appname for mutex name
cName = chrtran(this.cAppName, space(1), "")
* Use a specific property to identify this app
cProperty = cName + "_APP_SINGLE_INSTANCE"
this.hMutex = CreateMutex(0, chr(1), cName)
if GetLastError() = 183 && ERROR_ALREADY_EXISTS
* get the window handle of this window
nHwnd = GetActiveWindow()
* get the handle of the first window along
nNextHWND = GetWindow(nHwnd, 0)
* loop through each window to look for the property:
do while nNextHWND <> 0
* if window is not this handle and not a child
window
if (nNextHWND <> nHwnd and GetWindow(nNextHWND,
4) = 0)
if GetProp(nNextHWND, cProperty) = 1
* Determine if the application
* is minimized (an icon).
lIcon = (IsIconic(nNextHWND) #
0)
if lIcon
* It is, so restore it:
=WIN32_ShowWindow(nNextHWND, 9)
endif
* Attempt to set the window as
frontmost
=SetForegroundWindow(nNextHWND)
exit
endif
endif
nNextHWND = GetWindow(nNextHWND, 2)
enddo
* Release the window handle and mutex
CloseHandle(nHwnd)
* CloseHandle(hMutex)
this.ReleaseAppMutex()
else
lOnlyInstance = .t.
SetProp(_vfp.hwnd, cProperty, 1)
endif
return lOnlyInstance
endproc
procedure ReleaseAppMutex
local nResult
if this.hMutex # 0
nResult = WaitForSingleObject(this.hMutex, 50)
* 258 = STATUS_TIMEOUT
if nResult # 258
nResult = ReleaseMutex(this.hMutex)
* 1 equals Boolean TRUE
if nResult = 1
nResult = CloseHandle(this.hMutex)
endif
endif
endif
endproc
On Wed, Jul 15, 2009 at 9:45 AM, Dave Crozier<[email protected]> wrote:
> Eurico,
> Or you could use scripting if it is allowed:
>
> *******
> * Start of Code
> *
> LOCAL llQuit
> *!* Check for instance(s) of Myapp running
> oManager = GETOBJECT([winmgmts:])
> cQuery = [select * from win32_process where name='myapp.exe']
> oResult = oManager.ExecQuery(cQuery)
>
> IF oResult.Count > 1
> llQuit = .T.
> ENDI
> *!* Clean up
> oManager = .NULL.
> oResult = .NULL.
> RELEASE cQuery, oResult, oManager
>
> IF llQuit && Myapp.exe running twice
> QUIT
> ENDIf
> *
> * End of Code
> *********
>
> Dave Crozier
>
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On Behalf
> Of Eurico Chagas Filho
> Sent: 14 July 2009 12:12
> To: 'ProFox Email List'
> Subject: How to avoid two instances
>
>
> I came across a code written by Ramani to avoid two instances of an
> application in the same desktop.
> It uses extensively the DDE functions, is there anything I should be aware
> of ?
>
> TIA, E.
>
>
>
[excessive quoting removed by server]
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/profox
OT-free version of this list: http://leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message:
http://leafe.com/archives/byMID/profox/[email protected]
** All postings, unless explicitly stated otherwise, are the opinions of the
author, and do not constitute legal or medical advice. This statement is added
to the messages for those lawyers who are too stupid to see the obvious.