forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Preventing multiple instances of a program from running
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> ClearWin+
View previous topic :: View next topic  
Author Message
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Thu Dec 10, 2020 6:24 pm    Post subject: Preventing multiple instances of a program from running Reply with quote

How does one make sure that multiple instances of a program are not running?

There are some times where it would be useful to limit a user's ability to wrap themselves around a proverbial axle when programs crash due to file conflicts.

I've tried searching the HELP files and this Forum, but either my queries are too ambiguous or there's nothing there on this subject.

Bill
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7086
Location: Salford, UK

PostPosted: Thu Dec 10, 2020 7:41 pm    Post subject: Reply with quote

One way is to call the Microsoft function FindWindow. I can get details tomorrow if this is of interest.
Back to top
View user's profile Send private message AIM Address
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Thu Dec 10, 2020 9:07 pm    Post subject: Reply with quote

It is of interest to me. Sometimes my users don't remember that they have an instance running, then it will fail to open a file, and I get a frantic call (or e-mail). Better to let them know "we don't really support this".

Thanks,
Bill
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7086
Location: Salford, UK

PostPosted: Fri Dec 11, 2020 9:09 am    Post subject: Reply with quote

In this sample one or other of the arguments for FindWindow can be set to CORE4(0) or CORE8(0).

Code:
module mymod
use mswin
contains
logical function start()
integer(7) hwnd,h1
logical L
start = .true.
hwnd = FindWindow("SalfordDialog","My Editor")
if(hwnd /= 0)then
 !Not sure how many of these you need...
 L=SetForegroundWindow(hwnd)
 L=BringWindowToTop(hwnd)
 h1=SetActiveWindow(hwnd)
 h1=SetFocus(hwnd)
 start = .false.
endif 
end function start
end module mymod

winapp
program main
use mymod
integer iw
character*1025 buffer
if(start())then
buffer = " "
iw = winio@("%ca[My Editor]&")
iw = winio@("%pv%30.10re", buffer)
endif
end program main
Back to top
View user's profile Send private message AIM Address
Kenneth_Smith



Joined: 18 May 2012
Posts: 503
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Fri Dec 11, 2020 3:34 pm    Post subject: Reply with quote

My "clunky" solution is to use the presence of a file created by the first executable to block the second.

Code:
winapp
module test_mod
implicit none
integer :: block_unit=90

contains

! Checks to see if file exists, if it does STOP, otherwise create file.
  integer function init()
  integer ERROR_CODE
    if (FEXISTS@('status.txt', ERROR_CODE)) then
      STOP "Already running"
    else
     open (unit=block_unit,file='status.txt',status='new')
    end if
  init = 1
  end function init

! Deletes file at end of this run in preparation for next run
  integer function deinit()
  integer ERROR_CODE
    if (FEXISTS@('status.txt', ERROR_CODE)) close (unit=block_unit,status = 'delete')
    deinit=1
  end function deinit

  integer function main_code()
  integer i
    i = init()

    ! Main program calls go here, eg:
    do i = 1, 100000
      print*, i
    end do

    i = deinit()
    main_code = 1
  end function main_code

end module test_mod

program main
use test_mod
i = main_code()
end program main


Last edited by Kenneth_Smith on Fri Dec 11, 2020 6:42 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Fri Dec 11, 2020 3:46 pm    Post subject: Reply with quote

I tried setting the second parameter to core4(0) to get ANY class named "SalfordDialog". This caused an Access Violation in MAKE_CSTRING# (Checkmate Win32) so I wrote a smaller test program (error below).

Quote:
Runtime error from program:z:\fpstackfault\release\win32\forumtesting.exe
Access Violation
The instruction at address 1016ebd8 attempted to read from location 00000003

1016ebb0 MAKE_CSTRING# [+0028]
00401000 MAIN [+0059]


eax=00404320 ebx=0000484f ecx=00000004
edx=000000fe esi=0360fc64 edi=00000003
ebp=0360fc50 esp=0360fc2c IOPL=2
ds=002b es=002b fs=0053
gs=002b cs=0023 ss=002b
flgs=00010606 [NC EP NZ SN UP NV]

1016ebd8 rep
1016ebd9 scasb
1016ebda cld


I created a new function definition as:
Code:
stdcall findwindow_new 'FindWindowA' (string,ref):integer(7)


This does not crash.

It (usually) finds another application with the class name "SalfordDialog", but not always. Still trying to figure that one out.

Bottom line is: This can work!
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7086
Location: Salford, UK

PostPosted: Fri Dec 11, 2020 5:07 pm    Post subject: Reply with quote

Bill

If you don't match the caption then FindWindow will report the first ClearWin+ executable that if finds. They all have the same class name.

If you can identify your application from part of the caption rather than the whole then you could call EnumWindows and use it to read and test all of the captions in turn. This is a bit more tricky and is probably best done in a C function.
Back to top
View user's profile Send private message AIM Address
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Sat Dec 12, 2020 12:43 am    Post subject: Reply with quote

When I ran the test case (looking for SalfordDialog before my local window was created), I got mixed results.

So, I performed a getclassname() inside of the %sc call for the window that is created in the alternate path, while using the %hw to get the window handle in the "normal path".

In the normal case, it returned the value expected. In the other, it returns:
Quote:
SalfordDialog_win_icon0


I do use %mi and use the string 'win_icon' to specify the resource.

Is it possible that since I make the window [invisible] initially that the class name is different?

Bill
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7086
Location: Salford, UK

PostPosted: Sat Dec 12, 2020 9:35 am    Post subject: Reply with quote

Bill

Yes you have discovered something new to me.

ClearWin+ does register a class for a %mi icon. At the moment I don't know why it does that or if it is necessary.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7086
Location: Salford, UK

PostPosted: Sat Dec 12, 2020 1:05 pm    Post subject: Reply with quote

Bill

I think that you could call FindWindow twice. Once using SalfordDialog and once using SalfordDialog_win_icon0. You would also use your special interface for FindWindow (assuming that you don't know the precise caption).

If your application has only one %mi then SalfordDialog_win_icon0 will be unique to the application. If you have two %mi's then the first will have the class name SalfordDialog_win_icon0 and the second SalfordDialog_win_icon1 etc.

I am guessing that you will only get SalfordDialog_win_icon0 when the application is minimised but trial and error will tell.
Back to top
View user's profile Send private message AIM Address
jalih



Joined: 30 Jul 2012
Posts: 194

PostPosted: Sat Dec 12, 2020 3:37 pm    Post subject: Reply with quote

I think that instead of using FindWindow(), you should use named mutex to prevent running multiple instances of a program.

I once used following with MiniBasic code (Should translate to C++ easily):

Code:

func GUIDstr(), wstring
   GUID pGUID
   wstring str

   if CoCreateGuid(pGUID) = 0
      StringFromGUID2(pGUID,str,39)
   endif

   return str
endf


func app_mutex(), BOOL
   HANDLE hMutex

   hMutex = OpenMutex(MUTEX_ALL_ACCESS,0,GUIDstr())
   if hMutex = 0
      hMutex = CreateMutex(0,0,GUIDstr())
      return TRUE
   endif
   CloseHandle(hMutex)
   return FALSE
endf


' Following is for testing the app_mutex() function...
if app_mutex()
  print "Accuired mutex!"
else
  print "Already running!"
  do:until inkey$<> ""
  end
endif
 
do:until inkey$<> ""
Back to top
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Sat Dec 12, 2020 5:12 pm    Post subject: Reply with quote

Paul, it's always good to discover something new (?)! Actually, I enjoy digging deep, but sometimes it can be frustrating!

Yes, if the two names are unique, I can use this. I'll experiment to see if the icon resource I reference is different then the name follows this change. Could be useful, actually.

One problem I just uncovered with this scheme. I have a utility window that ends with %lw. After the window is created, I got the class name and it was "SalfordDialog_win_icon1". Closing the window, then starting it again and the class name is "SalfordDialog_win_icon2".

Luckily for me, the main window that always remains open is "0". I can live with that.

Something else to consider, something new!! [sarcasm]Oh joy![/sarcasm]
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Sat Dec 12, 2020 5:34 pm    Post subject: Reply with quote

If I change the icon displayed, the "_win_icon" changes to match the resource name used, but the sequential number remains and increments with each invocation.

Each window that is started by my "standard" method increments this trailing number.

Windows that are not created as "invisible" do have the default class name.
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1003
Location: Morrison, CO, USA

PostPosted: Sat Dec 12, 2020 10:26 pm    Post subject: Reply with quote

More discoveries.

The format code %nc allows you to set the class name of a window after you set the icon (but only if the icon would be normally be displayed). However, I could only use this once and have that window open when the next window was created (menu selection for example). Stated another way, subsequent windows from this first open window that used the %nc format code were met with this error:

Quote:
Runtime error from program:f:\cmasterf95\release\win32\c-master.exe
Run-time Error
Unable to register class C-Master

004208d0 WINDOW_SETUP [+0209] This builds the next window preamble and sets the same %nc value
00489060 CIMPORT_NEW [+04db] Menu selection starts the function call which build a new window
00420c90 WINDOW_ENDING [+0290] This starts the main window where the %nc is first used
00401970 NEWMAIN [+10a8]
00401000 main [+095a]


So, one cannot use this %nc format code unless all other windows that use this format code have been closed.

That said, when the class name was displayed in the first routine (NEWMAIN) (before the runtime error) there is no "_win_icon#" present. This means the name I had assigned is exactly what I intended, and I can then use that name without ambiguity if the same program starts again!
Back to top
View user's profile Send private message Visit poster's website
jalih



Joined: 30 Jul 2012
Posts: 194

PostPosted: Sun Dec 13, 2020 11:05 am    Post subject: Reply with quote

Keep in mind that using FindWindow() is not ideal, if there is possibility that multiple programs are started almost at the same time. It's not a bullet proof solution and might fail!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> ClearWin+ All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group