![]() |
Telelogic DOORS (steve huntington) | ![]() |
new topic :
profile :
search :
help :
dashboard :
calendar :
home
|
||
Latest News:
|
|
Topic Title: Preventing a script from starting two instances Topic Summary: Created On: 7-Jan-2009 15:13 Status: Post and Reply |
Linear : Threading : Single : Branch |
![]() |
![]()
|
![]() |
|
Hi everybody,
right now I'm trying to write a DXL script for which it shouldn't be possible to open more than one instance. Like when you have already opened the script it shouldn't be possible to open it again until you close it. Is this possible? If yes, how? I tried to find a solution for myself. I thought about setting an environment variable at the beginning of the script and testing if this variable is already set. If yes, than terminate the script immediately (which would be a second instance). However I wasn't able to create an environment variable. The code looks like that: if (platform == "WIN32") { string win_dir = getenv("windir") system win_dir "\\command.com /c set DOORS_SETPRODUCTDB_OPENED=true" } Even if it worked, I don't think this is a good solution, but if there's no other way, maybe this would be better than nothing... Hope you can help me with this. Cheers, Jochen |
|
![]() |
|
![]() |
|
Jochen, Using the registry could accomplish your goals if you are only concerned about limiting script on a single pc.
If you are concened about limiting script to one database you could use configuration files. Edited: 7-Jan-2009 at 17:10 by ron lewis |
|
![]() |
|
![]() |
|
It shouldn't be possible on a single PC to open the script twice at the same time. Several users are allowed to have the script opened at the same time (but each user only one instance). Ron, could you explain what you mean by "using the directory"?
Cheers, Jochen |
|
![]() |
|
![]() |
|
I meant registry when I said directory.
Looking at your code perhaps you need to revisit the dxl help on - getRegistry & -setRegistry Following is a simple demo: //DemoReadWriteRegistry /*(c) demo by Ron Lewis to show reading and writing to registry*/ string s = "HKEY_CURRENT_USER\\SOFTWARE\\DOORSlatch" string errMess = setRegistry(s, "Lock", "1") print errMess string sx =getRegistry(s, "Lock") print "if value is "sx"=1 then lock\n" errMess = setRegistry(s, "Lock","0") sx =getRegistry(s, "Lock") print "if value is " sx "=0 then unlocked" Edited: 7-Jan-2009 at 16:24 by ron lewis |
|
![]() |
|
![]() |
|
Ah ok, now I understand, thanks Ron
![]() Cheers, Jochen |
|
![]() |
|
![]() |
|
IT can inhibit user access to registry. While I have seen tight IT departments they usually don't go that far. If IT goes overboad, you may have to result to writing to disk drive.
Edited: 7-Jan-2009 at 16:34 by ron lewis |
|
![]() |
|
![]() |
|
How about this: put the session number in the name ..err.. title of the dialog, then ask Windows if there is a window open by that name. Surely someone out there knows how to make DOORS ask Windows if there is a particular window open.
string NameWindow = "MyXyzWindow_" (intOf(session())) ".txt" Perhaps take only the last 4 digits of the session, using the remainder function. The rest of this is mindless ramblings I wrote down before coming up with the above solution. -------------------------------------- From lazy memory instead of plowing through old code to prove it, this is what I recall when I went through this years ago. I wanted one instance of a script for each DOORS session. If you invoked DOORS twice you could get the script dialog twice. Having it invoked would not prevent someone else from having it invoked. I notice DOORS can indeed do this, the attribute editor window can have only one instance, even if you invoke it from another module. I also notice that when you invoke it, the dialog is updated with the newer object's information, losing what you were doing in the old one. Setting environment variables was easy via getenv() and setenv(), but these stayed residual forever. Setting environment variables via setRegistry() and getRegistry() and using the HKEY_Current_User area was a lot trickier to make work but eventually provided better functionality but again stayed residual forever. The problem of a DOORS crash preventing the script from ever running again was solved by clever use of the 'intOf(session())' command, but that caused problems with multiple instances of DOORS. Clevery naming the environment variable in upper case and prefixed with "DOORS", i.e. "DOORSCLEVERTEST" didn't work. Clever use of Config files didn't work either; except I almost got the exact functionality I wanted but you had to tolerate lots of 'confSysUser' files accumulating up over time, that had the session number in the name of the file. Perhaps this may work if the script was clever enough to remove old files that had session numbers older than 24 hours... Clever use of putting stuff in the Top Context of DXL via 'evalTop_' only worked the first time you invoked the dialog per session, since I have yet to be able to remove stuff from the top context and don't know how to change a value of a variable in the top context. Asking Windows if a there was a window open with a specific title worked for a single instance of DOORS, but not for multiple instances. I did prove the concept by creating some dummy module at the top of the project ..err.. in the database, and forced an association of having the dialog open and the module open read-invisibly at the same time and using triggers, but that was impractical. Never solved the problem. .................................. Now let me think outloud: use the confSystem area. Create a file name: "IsXyzDialogOpen_" and the integer version of the session number, e.g. string NameFile = "IsXyzDialogOpen_" (intOf(session)) "". The script checks the exisence of that file, if it exists then don't open the dialog, if it doesn't then create that config file and open the dialog. The dialog close button should be rerouted to a function that deletes the config file. This will fail in the very unlikely case where two DOORS users initiate their DOORS session in exactly the same second, and both try to use the script. Sick folks like me can overcome that by inserting the name of the local client machine into the name of the config file. The script can be coded to look for any confSystem file whose name starts with "IsXyzDialogOpen_" and whose integer session number is older than the integer version of today, and 24 hours (or 24*60*60 seconds). This will prevent crashed DOORS clients with the dialog open from accumulating lots of these files over time in the system area. Yuuuuuuuuck. - Louie |
|
![]() |
|
![]() |
|
You could use setenv and getenv, instead of setRegistry and getRegistry, which might have less chance of IT restrictions.
If your DXL is creating a dialog box, you could use "block", which will make the rest of DOORS insensitive to any input (preveting the user from running more DXL from the menu options) One unorthodox possibility... you could write to the main DOORS window title bar or status bar: string origTitle = getTitle(dbExplorer) if(origTitle!="Buzz off, I'm busy!") { setTitle(dbExplorer,"Buzz off, I'm busy!") // do your normal stuff here setTitle(dbExplorer,origTitle) } I don't think there is any DXL command that would specifically prevent a second instance of the same script (or any script). So, no matter what you do, you will have to build into the script some sort of check for an enviornment variable, a text file, etc. Thus, you can't prevent the second instance, only have the second instance exit quickly. It does seem I remember a thread about system commands that would check the task manager to see if certain windows were running. |
|
![]() |
|
![]() |
|
The best way I have found to accomplish this is to have the script try to create an IPC server connection on an unused port. The operation should succeed for the first instance of the script and should fail for subsequent invocations as long as the first instance of the script is still running. The code would look something like:
IPC ipc = server 2391 //nothing magic about '2391', just pick an available TCP port number if (null ipc) halt //halt since this script must already be running Normal clean-up during script termination would be 'delete ipc', but it appears that is handled automatically even if the script or DOORS terminates abnormally. |
|
![]() |
|
![]() |
|
Thank you guys, this was a big help. I tried out Roger's approach and it seems to work. I never used IPC before, are there any problems that might occur, besides that the port is already used?
Cheers, Jochen |
|
![]() |
|
![]() |
|
With IPC there's a small chance of client hard drive reformatting getting initiated, and a small chance of DOORS database corruption; but I wouldn't worry too much about that.
Just kidding. Picking the right port may be more complicated than just typing in a number; "who knows what evil lurks in the hearts of men" ..err.. IT folks. Also, you would need to pick another port for another script that wanted to do the right thing. As you suspect, I suggest you get some more info on the IPC stuff, hopefully Gallion can provide more info. - Louie |
|
![]() |
|
![]() |
|
I've never had a problem using the 'IPC server' technique at various customer sites. It does establish a new TCP stream socket on the client machine, but as long as the DXL script doesn't do an 'accept ipc', then the socket will never progress beyond the listening state. You can do a 'netstat -na' from DOS window while the script is running to see the status of the created socket.
In more security-conscious environments, one should probably discuss this approach with the security folks. Be sure to explain that the socket is just being used to prevent multiple instances of a DXL script on the client machine and that no communication is expected to occur on the socket. |
|
![]() |
|
![]() |
|
Don't know much about it, but it seems to me that hard coding a socket number in the script should be done only when you have some knowledge that that socket isn't being used for something else. It could be that the dialog won't even show up once if that socket is being used by some other program.
- Louie |
|
![]() |
|
![]() |
|
Not sure if this is helpful, but the object properties dialog is an example of a script that cannot be launched more than once.
This is done using a global variable for the DB. If it exists than the script uses it, otherwise it creates it. Very simple. ------------------------- Tony Goodman Smart DXL limited www.smartdxl.com |
|
![]() |
|
![]() |
|
Hi Guys,
As an alternate solution you might consider using the old tried and true file creation approach. When the scripts starts if checks for the existence of a file in a predetermined folder. if the file exists then the scipt must be running Once the script ends normally the file should then be deleted. Of course if the script crashes then the file would have to be deleted manually. I've used this method on occasion and have relatively good success. |
|
![]() |
|
![]() |
|
How can you use a global variable for the DB, like Tony mentioned? I tried to find the DXL Script for the object properties and I even found something, but when I open this file, I only get some weird characters, like the file is encrypted or something.
Currently I'm still using the IPC approach. I'm not completely happy with it, because of the possible port conflicts. But imo using a file or registry entry has the disadvantage, that there might be some write access problems and the problem after a crash. Cheers, Jochen |
|
![]() |
|
![]() |
|
.
Edited: 19-Jan-2009 at 17:13 by ron lewis |
|
![]() |
|
![]() |
|
You could perhaps overcome the crash-system-leaving-the-file-in-existence problem, by not just checking if it exists but getting its Stat and checking how old it is, perhaps the 'modified(Stat)' command. A file older than perhaps an hour should be deleted by the script which then proceeds.
- Louie Edited: 15-Jan-2009 at 15:52 by Louie Landale |
|
![]() |
FuseTalk Standard Edition v3.2 - © 1999-2009 FuseTalk Inc. All rights reserved.