I need to get the list of processes and ID’s running on a system. (like you would see in task manager) I want to be able to determine how many instances of my program are running on a machine because I want to be able to limit it if the user tries to start too many.
C++ Code Sample
This is the 64bit api.
This function is intended primarily for 64-bit applications. If the function is called by a 32-bit application running under WOW64, the dwFilterFlag option is ignored and the function provides the same results as the EnumProcessModules function.
An alternative 32bit snapshot api which can use QueryFullProcessImageNameA to get 32bit and 64bit processes.
Maybe something like BeginUnique() could be used instead of re-inventing the wheel. If you want to support more than one instance, I suppose you could test for multiple different names.
Or the Synchronisation Class and an iMutex.
Synchronization Objects
A Mutex is a very simple way to limit the user to having one instance of your program running at any time. The following example shows the use of the Name parameter for creating a Mutex and the TryWait method to limit your program in this way.
If you only want to run one instance of your app, you could always look at RunOnce from CapeSoft, but if you want to give the user a certain number of instances, this will not help.
I was using a MUTEX already. It had been in my application since it was in C6 (if not before). It continued to work fine in C9. When going to C11, I experienced 2 types of slowness (see my thread about slow SQL in C11 vs C9) The first slowness was if a user opened more than one instance of the EXE (some users are allowed up to 3). In this case, for instance 2 or 3, it was painfully slower. A window which i.e. The main form that usually takes about 1/2 - 3/4 second to load and fill (lots of SQL lookups here) was now taking 30-45 seconds and would not respond at all while it was filling. Secondally, all other times that SQL was being accessed, it was MUCH slower. I believe that the mutex was also impacting overall speed on what appeared to be screen changes (closing one screen, opening another) but, I strongly believe was the accessing of the database. Today, I ripped out the MUTEX and let as many instances run as I wanted and the speed problem instantly went away. I have replaced this with my reading of the processID’s for my program name and every time the program starts, I fill a queue with the process list, spin through the queue and count the number of instances of my program running.
Problem solved and working like a charm. Tomorrow, I will give the new version of the program to some of our heavy users and see if general overall speed is improved.
Thanks everyone for your ideas and suggestions.
You could also switch back to the C6 runtime if need be and try that.
But good luck with tomorrow. Any ideas why the mutex is slowing things down at this stage?
no clue why that is slowing it down. I might revisit that later but, I have resolved my issue and it is working as I need it to by looking at the process ID. This application is just internal to our company so, it is a fairly controlled environment and user base.
As an alternative, you could try just simple counting. ie when you start first thing you do is check a table and see how many times you’ve started. If it’s below the limit add an entry and continue. Remove the entry on exit.
Maybe Boxsoft Super Limiter BoxSoft Super Limiter can help
Until the workstation limit is reached because of an app crashed which has left the entry in the file.
An alternative is to have a timer event in each app which updates the current date/time file entry every 1 min.
Only downside is if the instance limit is reached, the user has to wait 1min to find out if all instances are still running, but if an app crashed, the user only has to wait 1min before being able to proceed using the app.
There is TToolHelp class in winapi.
There is WMI class in Active Scripting.
I’m sorry if this has been covered and I just missed it.
But how were you using the mutex?
Since you’re talking about allowing multiple instances, like 3
it seems to me that the object you want is a named semaphore where you can set the limit, vs using the mutex to manage your own counter.
So, the MUTEX has been in this application for over 15 years (put it before I was here) and has been working fine all that time through C55, C6, C9, and then caused problem in C11.1 Regardless, we were not only counting instances but were also storing and retrieving some information between the first instance and subsequent instances. This info was ‘basically static’ to each time user started / logged into initial instance. Regardless, yanking out the MUTEX and all the code relying on it and then just counting the instances of the exename in the windows process works fine. I just no longer pass the info between the instances which is fine and was more of a ‘nice to have’ than a necessity. The weird thing was that it killed the performance on my C11.1 compiled version of the same .app etc files that were being used in my C9 compiled version. I don’t understand why but, don’t have time to figure it out at this point as I have a different acceptable solution.
Havent looked at the class, but Windows has this info on the Mutex.
If more than one thread is waiting on a mutex, a waiting thread is selected. Do not assume a first-in, first-out (FIFO) order. External events such as kernel-mode APCs can change the wait order.
The above might account for your slow down, if its thread cycling in a time slicing way, if the isynch class allowed more than one object, but as @MarkGoldberg picked up on, you are limiting to 3 instances, so it makes me curious what your code is, and I wonder if there were any runtime changes to account for this in C11.1.
I know when I used mutexes in the past, I used the api’s direct to have more control as I couldnt get the iSynch class to work properly.
We can only imagine how you used a mutex so we can only guess why it appears to be creating a performance problem for you. Based on the description of limiting the number of processes I’d just expect it would be something that’s checked prior to launching the process or at process start up. Everything else should be unaffected.
This is one method I use, sometimes I need to allow 2 x instances so I count by program name.
Can you find & prototype the API calls or do you need help with that?
jhTools.ProcessCountByName PROCEDURE(STRING inProcessName)
equ:TH32CS_SNAPPROCESS EQUATE(2)
PE32 GROUP ! ProcessEntry32 Structure
dwSize LONG
cntUsage LONG
th32ProcessID LONG
th32DefaultHeapID LONG
th32ModuleID LONG
cntThreads LONG
th32ParentProcessID LONG
pcPriClassBase LONG
dwFlags LONG
szExeFile CSTRING(260)
.
hSnapShot LONG
dwFound LONG
Code
!-- Get Snapshot handle..
!--
hSnapShot = CreateToolhelp32Snapshot(equ:TH32CS_SNAPPROCESS,0)
IF hSnapShot <> -1 ! -1 = Invalid Handle
!-- Initialise PE32
PE32.dwSize = Size(PE32)
!-- Get info for 1st process ..
if Process32First(hSnapShot,ADDRESS(PE32)) = True
!-- is this what we're looking for?
IF UPPER(PE32.szExeFile) = UPPER(inProcessName)
dwFound = 1
.
!-- Look for other instances ..
!--
LOOP
IF Process32Next(hSnapShot,ADDRESS(PE32)) = TRUE
!-- is this out Process ?
IF UPPER(PE32.szExeFile) = UPPER(inProcessName)
dwFound += 1
.
ELSE
BREAK
.
.
.
!-- Close the Snapshot Handle
CloseHandle(hSnapShot)
.
!-- Return dwFound
RETURN(dwFound)
Thanks everyone. I have this working (sorry I didn’t let everyone know earlier). I appreciate everyone’s input.
What was your solution?
Sorry I didn’t let you know earlier … What you want may be built into Clarion. See the Frame Extension template “Add functionality to Frame” which has the option “Run Only One Instance”.
The temploate may not do exactly what you want but you’ll find the code for that in LibSrc in WinExt.clw that you can use. It uses the Tool Help API.