You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
How can I detect how many instances of a given program are running on a server? I need this information to block additional users if the licenced number of users has been reached.
I bet there is an API call for this, but I cannot find one!
Iain Johnstone
“None but those who have experienced them can conceive of the enticements of science” - Mary Shelley
>I bet there is an API call for this, but I cannot find one
I'll bet there isn't anything; you generally do this counting via your application.
"In theory" I suppose you could try logging on to the server, enumerating all the processes, getting the module names for those processes and looking at the file names for each process. If they are 'myprogram.exe' it's an instance of your program.
Of course, you can beat this one easily enough.. just rename the exe.
Then again, programs don't run "on a server", they run on the client.. unless you have a genuine client-server setup, in which case the server should count users in its own application logic.
(e.g, you can run \\computername\path\programfile.exe from a client machine and it will not show up in an enumeration of processes on the server).
I am looking at a Citrix setup where the app runs on the server. What I have at present is a counter in a file that is incremented each time the program is run as a separate instance, and decremented when a session terminates. However, if the user just crashes out of the app, the counter is not decremented. If this happens over time, the counter will reach the maximum number of users even though they are not there! I an fully aware that this is not the best system, but it is all I have at the present, hence the question.
Iain Johnstone
“None but those who have experienced them can conceive of the enticements of science” - Mary Shelley
Here is a routine that I use in my MP3 player found in the source code forum. It detects if the program is running on the same machine it's installed on.
You may be able to modify it to suit your own particulars.
Code:
'in the main body of the program
Title$ = "My running application '
CONSOLE NAME Title$ '
TitleName = Title$ ' This MUST match the console
' name.
IF Is_already_running(BYCOPY title$) THEN...
FUNCTION Is_Already_Running(TitleName AS ASCIIZ) EXPORT AS LONG
LOCAL hMutex AS LONG
hMutex = CreateMutex(BYVAL %Null, 0, TitleName)
IF hMutex = 0 THEN EXIT FUNCTION ' Error in Mutex
IF GetLastError = %ERROR_ALREADY_EXISTS OR FindWindow(TitleName, "") > 0 THEN
FUNCTION = %TRUE
END IF
END FUNCTION
I can't find where I got this routine from. My bad.
Iain,
if you want to play with registered Window messages
I'm pretty confident that you will acheive your goal.
Code:
#COMPILE EXE '#Win 8.04#
#REGISTER NONE
#DIM ALL
#INCLUDE "Win32Api.inc" '#2005-01-27#
%Label1 = 101
%MaxInstance = 3
'______________________________________________________________________________
CALLBACK FUNCTION DlgProc
STATIC WhosThere AS DWORD
STATIC ImHere AS DWORD
STATIC SetCount AS DWORD
STATIC InstancesCount AS DWORD
SELECT CASE CBMSG
CASE %WM_INITDIALOG
WhosThere = RegisterWindowMessage("WhosThere") 'Message to provoke the "ImHere" response
ImHere = RegisterWindowMessage("ImHere") 'Message to count instances
SetCount = RegisterWindowMessage("SetCount") 'Message to show instances count
PostMessage(%HWND_BROADCAST, WhosThere, 0, 0) 'Ask every instances to send a "ImHere" message
CASE WhosThere 'An new instance want to count total instances
PostMessage(%HWND_BROADCAST, ImHere, 0, 1) 'Send "ImHere" message with "1" to increment InstancesCount
CASE ImHere 'Respond to an "ImHere" message
IF CBLPARAM = 1 THEN 'Increment InstancesCount if 1
IF GetForeGroundWindow = CBHNDL THEN 'Are we foreground
INCR InstancesCount 'Increment InstancesCount
PostMessage(%HWND_BROADCAST, SetCount, 0, InstancesCount) 'Set InstancesCount to every instance
END IF
ELSE
DECR InstancesCount 'Decrement InstancesCount
PostMessage(%HWND_BROADCAST, SetCount, 0, InstancesCount) 'Set InstancesCount to every instance
END IF
IF InstancesCount > %MaxInstance THEN 'Check if maximum count is reached
IF GetForeGroundWindow = CBHNDL THEN 'Supress only the foreground windows
CONTROL SET TEXT CBHNDL, %Label1, "Sorry, no more than" & STR$(%MaxInstance) & _
"instances," & $CRLF & "quitting now !"
SLEEP 2000
PostMessage(%HWND_BROADCAST, SetCount, 0, InstancesCount) 'Set InstancesCount to every instance
DIALOG END CBHNDL 'End application
END IF
END IF
CASE SetCount
InstancesCount = CBLPARAM 'Set count total instances
CONTROL SET TEXT CBHNDL, %Label1, FORMAT$(InstancesCount) & " instance(s)" 'Show result
CASE %WM_DESTROY
PostMessage(%HWND_BROADCAST, ImHere, 0, 0) 'Say we're leaving to decrement InstancesCount
END SELECT
END FUNCTION
'______________________________________________________________________________
FUNCTION PBMAIN()
LOCAL hDlg AS DWORD
DIALOG NEW %HWND_DESKTOP ,"Max 3 instance", , , 150, 70, _
%WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, %WS_EX_TOPMOST TO hDlg
SetClassLong hDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION) 'Set a nice dialog icon
CONTROL ADD LABEL, hDlg, %Label1, "Instances count", 10, 30, 130, 20, %SS_CENTER, 0
DIALOG SHOW MODAL hDlg CALL DlgProc
END FUNCTION
'______________________________________________________________________________
The problem is... each instance of your program is actually executing in the memory space of the client computer.
So, the mutex approach could work if you do something like...
Code:
Enumerate all computers on the network
For each computer
Log on to that computer
look for mutex or other object with known name
If found
increment user count
end if
Next
If userCount > allowed
message to user and terminate
endif
You'd have to put this code into the client application.
Until there are no more crashes preventing update of the "user count file" I can't think of anything a whole lot better than this UNLESS you go to a true client-server application.. where each client must contact the server (which runs one instance on named machine) and that server application counts users and then responds to the starting client program that there is an insufficient number of licenses available for him to run right now.
Hmmm... maybe there would be a market for such a product? There has to be a market.. meaning 'somewhere' there almost certainly exists an off-the-shelf solution.
Not sure if it's so difficult to write a client/server app.
There is DCOM and there is TCP..
However, one can install an app twice isn't?
If you are willing to accept this fact then imo there is a more simple option i spoke about before.
You can let such an app seek a free spot in a file shared on a networkdevice.
(you will get permissionsissues though)
If you lock a single record in a random file you claim a single user this way.
If the app is exitted (or crashes ) the record is released again.
Seems a viable solution to me.
Michael - on the Citrix thin client system, the app (in fact all apps) execute on the server. The client end can be any old PC/terminal because it is just a screen and a keyboard (basically), though most of the users do not know/understand this, which is just as well!. As this particular installation is on a local authority network, I am keen to keep all the 'housekeeping' within the app just in case it goes pear-shaped.
Pierre & Mel - I will have a play with these suggestions. Fortunately I have a brother who is the ICT manager for a large London Borough that runs a Citrix systen, so I can get him to try out code before I attack the system at the other end of the country!
Many thanks to you all
Iain Johnstone
“None but those who have experienced them can conceive of the enticements of science” - Mary Shelley
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.
Comment