Link to home
Start Free TrialLog in
Avatar of Bruno Buesser
Bruno BuesserFlag for Switzerland

asked on

How to pass start parameters to an application that is started from a server in a Windows LAN

I write a Windows network application that can be launched over the LAN. On the server where the application resides runs also a Windows service that controls the license rules. When the application is started the application tries to establish a TCP connection to the service and sends some data. By this data the service can check if the application is allowed to run.
For the application<>service conversation I need the IP address of the server and the port the service is listening. I can programmaticaly find out the IP address of the server from where the application is started from but it's not possible to find out the port. I could set a fix port number in the application and in the service. But this is error prone since the port could also be used by another application of another company. So it's preferable to let the user change the port dynamically. I could do that easily in the service manager application where the administrator can change license settings.
Now my problem is, how can the service inform the instances of the application on which port they should connect to the service. As the application runs on clients, there is no way to read Registry settings of the server (right?). On XP servers the service manager could just write the port number into a file that the application could read easily as this file would be in its exe directory. But on VISTA servers I mustn't save or changes files into the program folder.

Can anybody tell me how such problems are normally solved?
Is there a way to pass some dynamic parameters when an application is started from the server?
What data can an application read from the server where it is started from?

Any comments are very appreciated.
Thanks, Bruno
Avatar of Louis LIETAER
Louis LIETAER
Flag of France image

You could have a .ini file in the same folder where you .exe is.
Avatar of Bruno Buesser

ASKER

An ini file is not possible in the VISTA case as it's is not allowed to write into the program directory. VISTA will redirect it to a folder in the user's profile. I should have a VISTA compatible solution. Or will this be possible from a Window service with no special rights?
>>>> But this is error prone since the port could also be used by another application of another company.
If two services would try to listen from the same port, at least one of them would fail. So, you would need to solve a probable issue of using the same port by two applications at the server anyhow and as it were more than 60000 numbers available, you have a good chance to find a unique number. I prefer to choose an odd number between 40000 and 50000 and never had a problem.  

Another possibility is to pass the port number when you launch your application. If doing so, you normally would pass the IP address or hostname as well.

A last idea is to compute the port number from the IP address, e. g. by concatenating the bytes numbers and taking it modulo 65536 (192.168.1.77 ==> 192168177%65536 == 16625).
You can place the INI file in the All Users folder.

Depending on the configuration, there might be different server ports for receiving and sending data.

===============
There are a LOT of different ways to approach this.  Here are some options:
* Use a server named reference and an application that returns the IP address, including the port
* You could query the 64K ports
* Copy the server file to the All Users folder if the current (local) configuration doesn't get results.  As part of the installation process, the latest configuration file should be copied.
* Use the handshaking to convey the latest configuration data

Bruno376,

Wouldn't it be even easier to use command-line arguments, and parse them in your client?

Really easy to do, let me know if you want more help, and what language your writing in.

Jake
@jake072

If this is running as a service, where does the command line come into play?
Thank you very much for all comments so far.
As I described in my question, I have written a windows service and a configuration program to change the settings in the service. In the configuration program I can load a license file that attaches the main application to the server and restricts the maximum number of instances. In this configuration program I can also start and stop the service and change the port. The IP address is not a problem as an instance started from the server hard disk can find it out programmatically.
When I change the port in the configuration program I wish that all instances will know it when they get started the next time. I don't want, that the administrator has to start the application on each client to change the port there or to edit any client settings. As the clients instances are started from the server disk there should be a mean to pass the port number.

As you suggested there will be several solution for this:
- Ini file in exe directory: Not applicable under VISTA as writing into exe dir is redirected to another directory
- Check a predefined range of port: Needs special programming to find out if the port belongs to another application. Possibly could slow down the program launch.
- Place the Ini file in the all user directory of the server: Can an instance running on the client access the all user directory on the server? Is this possible on any system? Is this a standard solution?
- Using command line parameter: When the port is changed by the configuration program it would have to edit the command line parameters of the program icon on each client.

I lack of deeper experience in server based application on the LAN and so I don't know how such things are normally solved and I fear if I select one solution I will get calls from customers from around the world complaining that they cannot run the application or changing the port does not work. There are so many LAN based application, so isn't there a standard procedure to solve such problems which runs reliably on any Windows LAN?
I work with Delphi 7. But my problem is more general and does not depend of the programming environment. I have enough experience in Delphi to solve any proposal.

Regards, Bruno
All Users folder is accessible without Vista bother.
Hi aikimark,
The path to all users folder depends on the Windows version. When I programmaticall ask that path on a client I get the path to the clients all users folder. Is it possible to ask the path to the server all users folder from an application running on a client which is started from the server?

Bruno  
You wouldn't normally place the file in an All Users folder on the server.  That folder would be used on the client systems to hold a local copy.  The local copy (config/ini) file would be placed in the All Users folder during installation.

You would normally create a folder on some shared directory to which the users are normally mapped.  You might be able to get away with a UNC mapping of the server folder as long as the folder grants anonymous Read Only access to the contents.  If I were doing this, I would probably include the application name as part of the directory name on the server, and maybe on the client as well.

aikimark & Bruno276,

The command line could be relevant...

Assuming your control program talks to the service, it would have to shut down the service, make whatever change is necessary, and then restart the service, no?

Thus, when restarting the server, that is where you could send it the new parameters... You would also have to change the command in the registry to load the service to include the command-line arguments.

Command-line arguments are easy to code, and readily available to services.

Jake

Bruno276,

One more quick thought...  That would require you to access the registry remotely, if I understand correctly, which could be a huge problem for you...

Perhaps it would be better to use the environment variables...

aikimark's suggestion... %ALLUSERSPROFILE% for a ini file...

Since services are computer wide and not user dependent, %ALLUSERSPROFILE% would be the best for your ini file, IMHO.

Jake
My system runs as follows:
At installation time I install 3 application on the server
1. My main application my clients wants to use
2. A Windows service that knows the license conditions and grants the instances of my application on the clients to start or order them to close after showing a message to the user.
3. A configuration program that lets to configure the service (load license file, change other settings, start and stop service). The configuration program must be started on the server and not on the clients.

So the Windows service and configuration program runs on server only and the user application runs on clients. The configuration program talks to the service through a Windows pipe. The user application on the client talks to the Windows service through a TCP connection. The whole time the user application is running on the client a TCP connection to the Windows service is kept open. When the Windows service unilaterally terminates the TCP connection due to license change or other settings changes the user applications on the clients would be shut down.

So when I change the port in the configuration program I don't need to stop and restart the service as the service would simply stop all TCP connections, change the port and starts again to listen to new connection requests.

I must first think about your comments in your last posts and will come back tomorrow.
Thanks, Bruno



if server talks with the client service, you could pass exchange information about the version of the config/ini file and send any updates.

you might want to make this a secured conversation and you might also want to consider separating this wake-up-in-lost/stupid-state from the regular conversations with the server, which can streamline the bulk of server traffic.
But when the application is not running on a client there is no talking between the service on the server and the application on the client.When the port is changed while the application is not running, the application must know the new number when it is started to call the service via TCP.
Avatar of rxfoster
rxfoster

Set up a configuration file on the server that is read by the client before they connect, then you only set the port definition in one location, per server. Or have the config stored on a share and automatically pulled from the client over SMB at each launch?
How often would ports change?
ASKER CERTIFIED SOLUTION
Avatar of rxfoster
rxfoster

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The port can only be changed by the configuration program. In most cases it will never changed as the default port will usually not conflict with another application.
I leaned from all your posts that there are some options to solve this problem but that there seems not to exist a standard solution that everybody use.
So I come back to the exe folder. The exe folder is really the simplest way to store a configuration file as all clients started from there can determine the path to there own exe folder easily and don't need any special installation work.
So my configuration program must be able to write into the exe folder of the application. Under XP this is no problem. Even as guest I can simply write in any subfolder of the program folder. But, as I mentioned at the beginning of this thread, under VISTA this is not so easy as the writing would be redirected into a virtual user subfolder. I read some papers about this procedure and learned that I have to study the UAC (User account control) under VISTA. There seems to be possible to write my configuration program in such a way that is runs with standard user rights and when I needs to do something for that it needs administrator rights (e.g. writing into a program subfolder) it requests the user to enter an administrator password. That could be an acceptable solution to my problem as changing ports is worth to request an administrator to do that.
I must first read more about this option and make some tests on a VISTA machine. I will report you my experiences afterward.        
So long! Bruno
Why not have the server listen on two ports? One would have a fixed value and the other would be changeable via configuration.
  1. Client conects to the server via the fixed port number.
  2. Server responds with the port number of the configured/variable port.
  3. Client then begins normal communications via that port.
@DanRollins,

I'm pretty sure the whole reason for this question is that he does NOT want to have a fixed port, in case there are conflicts...

Jake
The issue would be:
What, oh, what can the server do if, say, port 55555 is already in use when it comes to life.  If it is, the server can't listen on it and the clients will be unable to communicate with the server.
One solution to this problem is for the Server to attempt bind to the base port (55555) and it that fails, try the next higher number, 55556, and so forth until it succeeds.  Then the client does a similar process.  It attemtps to connect to 55555 and sends a query/test packet.  If it gets the expected response, then it's done.  If not, it tries the next higher port, and so forth.
Thank's for all your comments.
My solution I finally implemented is as follows:
I use a config file in the program directory of the application as rxfoster suggested. But that does only work in Vista when the service manager application has a Vista manifest and runs as administrator to prevent redirecting the config changes to a hidden user directory. The program directory seems to be the best place for this config file as it must be shared anyway and its easy to programmatically determine the UNC path to the application's exe folder.
I initially copy the config file with the default port in the exe folder by the installer and set the flag to "onlyifdoesntexist" for that this file is not overwritten by a second installation or an update or upgrade installation.

Bruno
The best place seems the exe folder of the application as it must be shared anyway and the application can easily access to its exe folder.