Jump to content

How to manage processes to avoid multiple executions?


Rece
 Share

Recommended Posts

I've written an initial program for my Win2000 terminal server which shows a menu with icons of executable programs. I wanted to avoid multiple executions (users can run the same program only once at a time). I use Run() to execute programs and then I store the PID of the executed program with the name of the user and the program. Later, when the user wants to execute a program I check the stored PID with ProcessExists() before running it. When the process with the stored PID already runs my program shows an error message otherwise it runs the program and stores the PID. The only problem is that Windows 2000 Server often gives the same PID if I run a program then I close it and then somebody runs another. So Processexists() shows that the program with this PID runs (it's true) but this process is not the same as which was stored by my program. So this method doesn't work... Has anybody another idea to avoid multiple executions? Users can log in from multiple client PCs at the same time but my program should not execute programs which run in any terminal session by the same user...

Or is it possible to set how often Win2000 gives the same PID for processes?

Link to comment
Share on other sites

I've written an initial program for my Win2000 terminal server which shows a menu with icons of executable programs. I wanted to avoid multiple executions (users can run the same program only once at a time). I use Run() to execute programs and then I store the PID of the executed program with the name of the user and the program. Later, when the user wants to execute a program I check the stored PID with ProcessExists() before running it. When the process with the stored PID already runs my program shows an error message otherwise it runs the program and stores the PID. The only problem is that Windows 2000 Server often gives the same PID if I run a program then I close it and then somebody runs another. So Processexists() shows that the program with this PID runs (it's true) but this process is not the same as which was stored by my program. So this method doesn't work... Has anybody another idea to avoid multiple executions? Users can log in from multiple client PCs at the same time but my program should not execute programs which run in any terminal session by the same user...

Or is it possible to set how often Win2000 gives the same PID for processes?

you could always just read the FAQ...
Link to comment
Share on other sites

OK but it is not so easy. This is a server. A lot of processes are running from the same program and users can log in from several computers at the same time. So if there is no window of the given program on my desktop the program can run in my other sessions. But how can I decide which processes belong to me?

Cameronsdad: which part of the FAQ?

Link to comment
Share on other sites

OK but it is not so easy. This is a server. A lot of processes are running from the same program and users can log in from several computers at the same time. So if there is no window of the given program on my desktop the program can run in my other sessions. But how can I decide which processes belong to me?

Cameronsdad: which part of the FAQ?

this one...

14. How can I make sure only one copy of my script is run?

The easiest way is to rename the title of the hidden AutoIt window when your script first starts. Then in the same script check for that window title existing - if it does then another copy of the script is running.

; Place at the top of your script

$g_szVersion = "My Script 1.1"

If WinExists($g_szVersion) Then Exit ; It's already running

AutoItWinSetTitle($g_szVersion)

; Rest of your script goes here

Back To Top

and i didn't mean to sound condescending, just so you know. Edited by cameronsdad
Link to comment
Share on other sites

I do not think that Rece can use FAQ #14... but I'm not sure I understand Rece's first post.

Let me see if I understand the task at hand:

Rece said, "I've written an initial program for my Win2000 terminal server..."

[This would be an AutoIt script that runs on the server, but is viewed and used by the end user at the client system via a terminal session...]

Rece: "[a script]...which shows a menu with icons of executable programs."

["executable programs" would be commercial apps served up by the W2k terminal server.]

Rece: "I wanted to avoid multiple executions..."

[Rece wants to avoid multiple executions of the commercial apps - not the menu script.]

Rece: "I use Run() to execute programs and then I store the PID..."

[Rece: explains what has been tried and why it will not work.]

Rece: " Users can log in from multiple client PCs at the same time but my program should not execute programs which run in any terminal session by the same user..."

[Rece restates the original problem another way - I assume that "my program" = the menu script - I also assume that "execute programs" are the commercial apps running on the server.]

I cannot say that I've ever worked with this type of environment, but I would assume that there is one copy of the "menu script" (running on the server) for each terminal session connected. Having multiple instances of that "menu script" running on the server is not the problem. Having one end user open one terminal session and then one commercial app is okay. Having that same end user open another concurrent terminal session and then open another concurrent copy of that same commercial app is not okay - and hence the post to the forum.

One user consuming two licenses of the commercial apps is something that I would assume the W2k terminal server [host] should be able to manage, but I saw no such feature in my brief research on the topic.

My apologies if:

...I've misinterpreted the first post...

...I've missed how FAQ #14 applies here.

I have no clue how to solve this problem, but I hope that I've correctly restated it for those that know far more than I about AutoIt.

[size="1"][font="Arial"].[u].[/u][/font][/size]

Link to comment
Share on other sites

Yes Herewasplato you understand my problem!

My script runs commercial programs so I can't use the FAQ because I can't affect the windows of that programs...

Yes, it is not a problem if my script runs in multiple sessions but it is a problem if the commercial softwares run in multiple sessions of the same user. And every user runs the same program...

Link to comment
Share on other sites

Yes Herewasplato you understand my problem!

My script runs commercial programs so I can't use the FAQ because I can't affect the windows of that programs...

Yes, it is not a problem if my script runs in multiple sessions but it is a problem if the commercial softwares run in multiple sessions of the same user. And every user runs the same program...

I'm sorry, i definitely misunderstood on this one...
Link to comment
Share on other sites

...because I can't affect the windows of that programs...

When one user starts one terminal session, launches your menu script and then launches one copy of a commercial app... can your "menu script" "see" the window of that commercial app?

If the script can "see" the window launched within a terminal session, then you can monitor it for closure. You already know which user starts which app, you just need to know when the app closes. Then pick a method of having the scripts "talk to each other" - maybe thru text files on the server.

[size="1"][font="Arial"].[u].[/u][/font][/size]

Link to comment
Share on other sites

If the script can "see" the window launched within a terminal session, then you can monitor it for closure.

How can I monitor when a program is closed? The executable apps have different window titles and it is configurable which program a user can execute...
Link to comment
Share on other sites

How can I monitor when a program is closed? The executable apps have different window titles and it is configurable which program a user can execute...

I'm going to assume from your response that your "menu script" can "see" the windows within a given terminal session. In other words, functions like WinWait will work as expected. I would really like to know for sure that this is the case before spending too much more time on this. Can you run a simple test within a terminal session like:

Run Notepad.exe

WinWait Notepad

As for dealing with the title changing for a given window:

When one button is pressed on your menu script,

disable all other buttons for starting other apps until this

code has completed to find out what app was started:

Start the app with the window hidden from the user,

then find out what app the user started,

then check to see if they already have that app open elsewhere.

Unhide the app if all is okay or scold the user.

AutoItSetOption("WinTitleMatchMode", 2)

$ComAppTitleArray = StringSplit("Notepad,Word,Excel", ",")

;this is a list of all possible apps on the server

For $i = 1 to Ubound($ComAppTitleArray[0])

If WinExists($ComAppTitleArray[$i]) Then...

this is the app that was started

(Let's say that the user started Word.)

check if FileExists in the folder for user xzy named Word.txt

if it is there, the user has Word open elsewhere

If not there:

make a file in the folder for user xzy named Word.txt

unhide the app for the user

add the name of this app to a string that is part of a loop to watch for app closures

Perhaps you could use adlib to watch for window closures:

$AppsOpenArray = StringSplit($AppsOpen, ",")

For $i = 1 to Ubound($AppsOpenArray[0])

If NOT WinExists($AppsOpenArray[$i]) Then...

remove the file in the folder for user xzy named Word.txt

let me know...

Edited by herewasplato

[size="1"][font="Arial"].[u].[/u][/font][/size]

Link to comment
Share on other sites

This is a very good idea but my users should be able to run multiple programs simultaneously...

And every user runs the same programs with the same window titles...

Edited by Rece
Link to comment
Share on other sites

Opt("RunErrorsFatal", 0) ;1=fatal, 0=silent set @error

$SCRIPT_NAME=@ScriptName

$P_LIST= ProcessList($SCRIPT_NAME)

If $P_LIST[0][0] >= 2 Then

MsgBox(0,"WARNING", "Script already running",5)

Exit

EndIf

$ctr=0

While 1

Sleep(1000)

If $ctr >= 100 Then ExitLoop

$ctr=$ctr+1

WEnd

here a snippet that will not run the program if already exist

-----------------------------------------------------------BSECE, MCPAIM: juliusrmsYM: jivy_21@yahoo.comMSN: juliusLramos@hotmail.comMobile #: (Globe): +639167031989Web: http://www.trendmicro.com

Link to comment
Share on other sites

Julius Ramos, psandu.ro: thanks but please read the previous messages before posting...

A client can log in to my terminal server from multiple computers simultaneously. This means that several terminal sessions and several "menu scripts" of the same user are running at the same time. It is not a problem. My "menu script" is executed only when a user logs in, they can not start it any other way.

When a user executes the same commercial application (from the menu) more then once at the same time it is a problem. But all users are running the same applications with the same program names and window titles. So I can not check the multiple executions from the process list or by getting window titles...

I tried to store the PIDs of the executed programs and check it before execution but it doesn't work because Win2000 gives the same PID for a program if the previous program with that PID has already been closed...

Link to comment
Share on other sites

  • Moderators

Julius Ramos, psandu.ro: thanks but please read the previous messages before posting...

A client can log in to my terminal server from multiple computers simultaneously. This means that several terminal sessions and several "menu scripts" of the same user are running at the same time. It is not a problem. My "menu script" is executed only when a user logs in, they can not start it any other way.

When a user executes the same commercial application (from the menu) more then once at the same time it is a problem. But all users are running the same applications with the same program names and window titles. So I can not check the multiple executions from the process list or by getting window titles...

I tried to store the PIDs of the executed programs and check it before execution but it doesn't work because Win2000 gives the same PID for a program if the previous program with that PID has already been closed...

It doesn't say here that this 'program' was written in AutoIt, so I'm going to assume that since this is an AutoIt forum, and you haven't stated otherwise, that it was.

The singleton() will work then, it will set a unique flag for your program upon execution (after logging on) and you can set it to exit the script it's trying to open at that time, display an error message and exit, or just display an error message. (I suggest the error message because it will prevent them from trying multitudes of times). Although I don't use mine based via a server, I'm 100% confident my end user is not running multiple copies at one time, because I set the parameter for that exe at time of execution with the flag that the singleton() creates.

I have not used the one via the forum, I only use Valik's original one:

Singleton("Put the flag name that will be used by this executible (make it unique)")


Func Singleton($semaphore)
    Local $ERROR_ALREADY_EXISTS = 183
    DllCall("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $semaphore)
    Local $lastError = DllCall("kernel32.dll", "int", "GetLastError")
    If $lastError[0] = $ERROR_ALREADY_EXISTS Then 
        MsgBox(16, "My Program Name Error", "Error 404" & @CRLF & "This program may not run multiple instances of itself")
        Exit -1; exit the program they just tried to open (not the one that is currently open)
    EndIf
EndFunc; Singleton()

Put that right after the verification that it's ok to run the exe since they have logged on.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Hi Rece I don't know much about terminal server but you mention that you save the PID. How about if you try to used a ini file as a log in which everytime your script runs records the user name, application running, the pid and when the user close the app remove it from the ini file. Something like this:

[userName]

notepad.exe=123456

worpad.exe=9876541

explorer.exe=456712

This way if the same user open another terminal, you script can check if the app that the user trying to rerun is already in the ini file then compare if the PID is equal to the same App.exe and give to the user a message that they are already running that application and need to be terminated before they can used again.

Edited by Danny35d
AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line
Link to comment
Share on other sites

Danny35d: that was exactly what I have tried but it doesn't work as I have written. I give you an example:

User "A" runs notepad.exe. The PID is 1234. My menu program stores it:

[A]

notepad.exe=1234

User "A" closes notepad.exe.

User "B" runs notepad.exe. The PID is 1234. (Yes, it can be, this is the problem.)

User "A" tries to run notepad.exe again. My program loads "notepad.exe=1234" from the INI file and makes a ProcessExists(1234) check. Process 1234 runs and my program gives an error message to user "A". But user "A" should be able to run notepad.exe...

SmOke_N: my menu script was written in AutoIt, the commercial applications don't...

It is not my program which should not run more than once simultaneously. Every user runs it once or more.

The commercial applications can be executed more than once simultaneously but not by the same user. Will Singleton() work then? Can I use it for the commercial apps? I think it will not apply only for the current user but all of them...

Link to comment
Share on other sites

Rece I believe that the only part that your are missing is removing apps from ini file when app closed:

User "A" runs notepad.exe. The PID is 1234.

[A]

notepad.exe=1234

User "A" closes notepad.exe.

At this point your script remove the entry of notepad.exe from the ini file.

[A]

User "B" runs notepad.exe. The PID is 1234.

User "A" tries to run notepad.exe again

Check ini file apps not there, make the entry to the ini file notepad.exe=1234 run notepad.exe to user A

Now User A run another Terminal and try to rerun notepad, Check ini file app is there, makes a ProcessExists(1234) check. Process 1234 runs and Process 1234 is equal to notepad.exe (you want to be sure that PID 1234 is the same application that user A is trying to run) your program gives an error message to user "A".

Edited by Danny35d
AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line
Link to comment
Share on other sites

User "A" closes notepad.exe.

At this point your script remove the entry of notepad.exe from the ini file.

OK I know this but I don't know how to do it. I can't use RunWait() or WinWait() because the user should be able to start other programs before closing the first. So again:

How can I monitor when a program is closed?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...