473,385 Members | 2,013 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Installing Windows Service with Configurable Name

Hi All

I would like to install the same Windows Service project on the same server
under different names, one for each customer. I have been able to do it but
I would like an expert opinion as to whether my solution is robust or whether
there is a better way to do it.

What I've been trying to do is to create a core project with different
extension projects, one for each customer. I wanted to create a different
Setup project for each customer where each Setup project included the primary
outputs of the core project and the appropriate customer extension project.

In the end I found I needed to create 4 projects:
1) The Core project, with abstract base classes that are extended by the
customer extension projects.
2) The Customer Extension projects, each one of which contains classes that
inherit and extend the base classes in the Core project. These Customer
Extension projects reference the Core project.
3) An EntryPoint project that provides the entry point of the application.
It looks for a customer extension assembly in a sub-folder of the application
folder and loads it, if found. It then starts the Windows service. The
Windows service uses the classes in the customer extension that has been
loaded. This project also references the Core project.
4) The Customer Setup projects. Each one installs the application as a
different Windows service. Each setup project includes the primary outputs
of the EntryPoint project and the appropriate Customer Extension project.

I wanted to include only the minimum functionality in the Customer Extension
projects so it would be easy for junior developers to add new customers
without problems. As a result, I tried to find a way of including just one
Service.cs class and one Installer.cs class in the EntryPoint project, and
configuring them so each Customer Setup project would install the application
with a different service name.

As far as I could see I would need to make the following three properties of
the Installer class configurable: the ServiceName, the DisplayName and the
Description. I would also need to make the following property of the Service
class configurable: ServiceName.

Initially I tried reading the properties from a config file but it appeared
it was not possible for the Installer class to read the config file during
installation. I then tried reading the properties from a resx file. That
seemed to work. So now I've added a resx file to each Customer Extension
project. Each resx file contains 3 entries: ServiceName, DispalyName,
Description. Each Customer Setup file copies the resx file from the
appropriate Customer Extension folder to the application folder. If I run
the MSI files created from each Customer Setup project I can install the same
application on the same server with different customer extensions as
different Windows services.

Here is the code in the Installer class that sets the three configurable
properties (where the installer class is called ServiceInstaller and
MiscLiterals is a static class containing all the string literals in the
project. serviceInstaller1 is an instance of
System.ServiceProcess.ServiceInstaller):

[RunInstaller(true)]
public partial class ServiceInstaller : Installer
{
public ServiceInstaller()
{
InitializeComponent();

// Read service properties from the resx file (will override the
properties specified in the Designer).
// Assumption: The resx file has been copied from the customer extension
project to the JBEEntryPoint
// application folder by the service setup project.
Assembly assy = Assembly.GetExecutingAssembly();
string resxPath = Path.GetDirectoryName(assy.Location);
string resxFile = Path.Combine(resxPath,
MiscLiterals.ServicePropertiesFile);

try
{
ResXResourceReader rsxr = new ResXResourceReader(resxFile);
foreach (DictionaryEntry de in rsxr)
{
switch (de.Key.ToString().ToLower())
{
case "servicename":
this.serviceInstaller1.ServiceName = de.Value.ToString();
break;
case "displayname":
this.serviceInstaller1.DisplayName = de.Value.ToString();
break;
case "description":
this.serviceInstaller1.Description = de.Value.ToString();
break;
}
}
rsxr.Close();
}
catch (Exception xcp)
{
//Do nothing for the moment.
}
}
}
}
Here is the code in the Service class that sets the ServiceName property
(where the service class is called JBEService, Plugins is a structure
containing the classes from the Customer Extension assembly that was loaded,
and Logging is a similar static class to MiscLiterals):

partial class JBEService : ServiceBase
{

// Initialize the trace sources.
static TraceSource _mainLogSource = new
TraceSource(Logging.MainTraceSource);
static TraceSource _inwardsLogSource = new
TraceSource(Logging.InwardsTraceSource);
static TraceSource _outwardsLogSource = new
TraceSource(Logging.OutwardsTraceSource);

Plugins _pluginsLoaded;
public JBEService(Plugins pluginsLoaded)
{
InitializeComponent();

_pluginsLoaded = pluginsLoaded;

// Read service name from the resx file (will override the name specified
in the Designer).
// Assumption: The resx file has been copied from the customer extension
project to the JBEEntryPoint
// application folder by the service setup project.
Assembly assy = Assembly.GetExecutingAssembly();
string resxPath = Path.GetDirectoryName(assy.Location);
string resxFile = Path.Combine(resxPath,
MiscLiterals.ServicePropertiesFile);
try
{
ResXResourceReader rsxr = new ResXResourceReader(resxFile);
foreach (DictionaryEntry de in rsxr)
{
if (de.Key.ToString().ToLower() == "servicename")
{
this.ServiceName = de.Value.ToString();
break;
}
}
rsxr.Close();
}
catch (Exception xcp)
{
string errMessage = string.Format("Exception while attempting to read
service name from resource file: {0}",
xcp.Message);
_mainLogSource.TraceEvent(TraceEventType.Error, 605, errMessage);
}
}

....More code, such as OnStart, OnStop, down here....

As I mentioned at the top of this post, this seems to work but I'm not sure
how robust it is. One of our system admins has told me a version of the
application installed on a Windows 2000 server did not auto restart when they
rebooted the server, although the service was set to auto start. I haven't
had any problems with the application auto restarting when testing on a
Windows XP SP2 machine, though. The application was developed using .NET 2.0.

Cheers
Simon
May 18 '07 #1
0 2662

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Ken Lindner | last post by:
I have a need to become familiar with SQL Server 2000 for work. Needless to say I am new to SQL Server any version, but not IT in general. My employer has provided me with the SQL Server 2000...
0
by: Chris Halcrow | last post by:
Hi I've spent ALL DAY trying to re-install SQL Server 2000 on Windows XP. I continually get the error 'cannot configure server' just at the end of the installation. I've tried the following: ...
2
by: Russ McDaniel | last post by:
Originally posted to microsoft.public.dotnet.distributed_apps with no response. Reposted here with additional thoughts. --- Hello, I'm writing a Windows service which performs some...
9
by: Hardy Wang | last post by:
Hi all: I read an article from http://www.c-sharpcorner.com/Code/2003/Sept/InstallingWinServiceProgrammatically.asp about how to install a windows service programmatically. Based ont the code...
11
by: tshad | last post by:
I have a small Windows Service program that just has a timer on it and it built fine. I try to install it using InstallUtil and I get the following message: ...
2
by: J | last post by:
hi, I'm having a problem installing a service created in vb.net 2003 on a windows 2000 server. I have installed the service on a few XP machines with out any problems...but the 2 servers (win...
5
by: Andrea Vincenzi | last post by:
Help me please, I'm totally stuck! My Visual Studio 2003 debugger stopped working after I installed Windows XP Service Pack 2. Here is what happens (with any project, even a "Hello, world"...
13
by: dancer | last post by:
I have made a new post because when I try to respond to another, I get the error, "Article Rejected -- Ill-formed message id" This is in response to the advice of Juan Libre to install Net...
3
by: desmond001 | last post by:
hi i ve started to do my desing guys this is my first time i do this a windows service, developed in C#, which is able to do the following. - Encapsulated in an MSI or setup application...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.