Multiple Instances of a Service on 1 box

G

Guest

Hi,

I am trying to create a Windows Service in C# that will install on a single box to support multiple environments. I have created the service and it works perfect. Now however, the client has decided to run multiple environments of the application (a web app) on the one box (i.e. production, acceptance & training). The problem is that the service also needs to run in each environment with it's own configuration settings.

I found an article from this newsgroup from Patrick Lam (MAY 2002) that sounded like it was what I needed but couldn't really get it to work. Is there any examples of how I could modify my existing service code so that the name of the service etc is something I can have entered during the installation process and that information is configured dynamically etc so that multiple copies of the service installation exe's are put into seperate directories and therefore can be totally independant of one another. That way the acceptance environment can be updated with the newer version without affecting production and vice versa.

This way I would run the setup package enter a name (e.g. "Production") and get something like:
Processor Service - Production

installed on the box.

I could then run the setup package again, not get told the product is already installed, and enter another name (e.g. "Acceptance") and end up with:
Processor Service - Acceptance
Processor Service - Production

listed in the Services manager.

Effectively what I want to end up with is something very much like SQL Server 2000 where each service can be stopped and configured and upgraded individually. Therefore, I would also need to be able to remove the indivdual services as well if required.

Will try anything at least once.

FYI: I am using VS2002 EA, Framework 1.0 SP2 and the standard included installer solutions.

Thanks,
Mark
 
G

Gary Chang

Hi Mark,

Thanks for posting in the community.

Currently I am looking for somebody who could help you on it. We will reply
here with more information as soon as possible.
If you have any more concerns on it, please feel free to post here.


Thanks!

Best regards,

Gary Chang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
 
F

Felix Wang

Hi Mark,

Thanks for posting. I have briefly reviewed Patrick Lam's post. I believe
the story is not that simple.

If you would like to use Setup project to deploy the Service, you have to
make use of MSI transform, since we cannot install the same MSI package on
one system multiple times (per machine or for the same user).

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/t
ransforms.asp?frame=true

If we take a detailed look on the MSDE setup program, we can find 16 MSI
files. They correspond to the 16 (maximum number) instances of the MSDE.
When we launch the bootstrap EXE ("Setup.exe") the correct MSI is picked
and used.

I hope the information is useful to you.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Hi Felix

Thanks for the info. I have read the articles on transformations and completed the samples, but now have some questions

I have created the MNP2000.msi and MNP2000t.msi databases and the associated MNPTrans.mst file by doing the example

http://msdn.microsoft.com/library/d...customization_transform_example.asp?frame=tru

I have now tried to install this sample to simulate the multiple environments I am going to need for my Windows Service installation, but I have found that the result is I can only effectively install it once. The transformation works and I end up with a slightly different version than using the base database to install the product, but I cannot install both versions at the same time. If I run the installer using the command line

msiexec /i MNP2000.ms

I end up with a default installation of the sample ap

if I then run (as specified in the article)

msiexec /i MNP2000.msi TRANSFORMS=MNPtrans.ms

I do not get the fresh installation screen as I expected but the Repair, Modify, Remove window

I have tried modifying the product name of the package (MNP2000t.msi) and supplied some new guids and this then enabled me to run the separate packages and install it twice, but I couldn't run it applying the transformations to MNP2000t.msi. I am now wondering if I am doing what needs to be done, or am I in fact simply hacking the database and possibly digging myself a very deep hole

Is there any information available on what I am trying to do or what is in the MSDN Library it? Also, the sample relies very heavily on the SDK and the tools assocaited with that (i.e. Orca and MsiInfo), is there a way to do this using the Windows Installer features in the VS IDE? Do third party products like WISE or InstallShield have support for these types of installations

Thanks
Mar
 
F

Felix Wang

Hi Mark,

Thanks for your feedback. In fact, Transform may be necessary but not
sufficient to achieve the goal.

Transform can change the installation database and tables. However, it
cannot modify the summary information stream. In order to achieve the goal
of multiple installation. We need to change at least 2 things in the MSI,
the product code and the package code. It is likely that we need to change
the upgrade code as well. Through applying a Transform, we can modify the
ProductCode and the UpgradeCode properties in the "Property" table.
However, the PackageCode is stored in the summary information steam, which
is not modifiable solely with Transform.

I would still suggest that we make reference to the MSDE installation
program, which uses 16 separate MSIs. As far as VS.Net Setup project is
concerned, we have the option to package files "As loose uncompressed file"
or "In cabinet files" (in the project property settings). As a result, we
only store the basic database information in the MSIs and we can re-use the
external files for different MSIs.

If you would like to run multilple .Net Windows Services, I think we cannot
hard code the service name in the ServiceInstaller class. Instead, we may
need to read the service name from an external source, so that it is
configurable. The service name is used to identify the service under the
regsitry key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\".

I hope this helps.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Hi Felix

I have managed to get the Installer Packages customised and am able to now install multiple environments on the single server. The script I use is included below for anyone who may find it handy. I have discovered one issue with all of this which if anyone knows the answer to, I would appreciate it

When uninstalling the packages, the entry defining the service in the registry is not removed although the applications directory is. This occurs for all environments except for whichever one was the last one installed in which case the unistall process works correctly

As far as the script is concerned below, it works by reading an XML file that I have defined that has all my environments defined and I loop through that and create a separate install directory for each. Not the most efficient way but it does the trick

The important file is the Settings.xml file as this file is read during the install process by the installer class to configure the name of the service I am installing

Ciao
Mar

' ============================================================================
' Script : BuildEnvironmentPackages.vb
' Description : Builds a series of installer packages for supporting multipl
' environments on a single bo
' Author : Mark Durego
' Created : March 200
' Copyright : KAZ Technology Service
' ============================================================================
' Arguments : 0 - Original Database Director
' Arguments : 1 - Environment List Fil
' ============================================================================
' Revision History



Option Explici
'On Error Resume Nex

Dim
Dim WshShel
Set WshShell = Wscript.CreateObject("Wscript.Shell") : CheckErro

' Check argument
If WScript.Arguments.Count < 2 The
WScript.Echo "Usage is: [CScript.exe|WScript.exe] BuildEnvironmentPackages.vbs [original database directory] [environment list file]
WScript.Quit
End I


' Open the environment list fil

Dim environmentsFile : Set environments = Nothin
Set environmentsFile = WScript.CreateObject("Msxml2.DOMDocument.4.0"
environmentsFile.Load(WScript.Arguments(1)
Dim environments : Set environments = environmentsFile.getElementsByTagName("environment"

Wscript.Echo "
Wscript.Echo "porteco Processor Service
Wscript.Echo "Environment Installer Builder
Wscript.Echo "
WScript.Echo "There are " & environments.length & " environments defined in the file.
Wscript.Echo "

Dim fso : Set fso = WScript.CreateObject("Scripting.FileSystemObject"

For i = 0 to environments.length -


' Copy the original installer folder to a new folder named by the environmen

Dim name : name = environments(i).getAttribute("name"
Dim path : path = ".\" & nam
fso.CopyFolder ".\" & Wscript.Arguments(0), pat
Wscript.Echo "Building " & name & " environment installer


' Modify the settings.xml file in the new environmen

Dim settingsFile : Set settingsFile = WScript.CreateObject("Msxml2.DOMDocument.4.0"
settingsFile.load path + "\Settings.xml
Dim environmentNode : Set environmentNode = settingsFile.selectSingleNode("/settings/environment"
environmentNode.setAttribute "name", nam
settingsFile.save path + "\Settings.xml


' Connect to Windows Installer objec

Dim installer : Set installer = Nothin
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckErro


' Open databas

Dim databasePath : databasePath = path + "\Installer.Msi
Dim database : Set database = installer.OpenDatabase(databasePath, 1) : CheckErro


' Add the component definitio

Dim sqlQuery : sqlQuery = "INSERT INTO `Component` (`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) VALUES (?, ?, ?, ?, ?, ?)" : CheckErro
Dim view : Set view = database.OpenView(sqlQuery) : CheckErro
Dim record : Set record = installer.CreateRecord(6) : CheckErro
record.StringData(1) = "EnvironmentSettings
record.StringData(2) = "{7DC4F5B0-594C-4B0E-BD36-CAA613D0ACF1}
record.StringData(3) = "TARGETDIR"
record.IntegerData(4) = 0
record.StringData(5) = ""
record.StringData(6) = "Settings.xml"
view.Execute record : CheckError
view.Close

'
' Add the file definition to the component
'
sqlQuery = "INSERT INTO `File` (`File`, `Component_`, `FileName`, `FileSize`, `Version`, `Language`, `Attributes`, `Sequence`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
Set view = database.OpenView(sqlQuery) : CheckError
Set record = installer.CreateRecord(8) : CheckError
record.StringData(1) = "Settings.xml"
record.StringData(2) = "EnvironmentSettings"
record.StringData(3) = "Settings.xml"
record.IntegerData(4) = 1000
record.StringData(5) = ""
record.StringData(6) = ""
record.IntegerData(7) = 0
record.IntegerData(8) = 1
view.Execute record : CheckError
view.Close

'
' Add the component to the feature
'
sqlQuery = "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES (?, ?)"
Set view = database.OpenView(sqlQuery) : CheckError
Set record = installer.CreateRecord(2) : CheckError
record.StringData(1) = "DefaultFeature"
record.StringData(2) = "EnvironmentSettings"
view.Execute record : CheckError
view.Close

'
' Update the installation path
'
sqlQuery = "UPDATE `CustomAction` SET `Target` = ? WHERE `Action` = 'DIRCA_TARGETDIR'"
Set view = database.OpenView(sqlQuery) : CheckError
Set record = installer.CreateRecord(1) : CheckError
record.StringData(1) = "[ProgramFilesFolder][Manufacturer]\porteco Processor Service\" & name
view.Execute record : CheckError
view.Close

'
' Update the properties
'
sqlQuery = "UPDATE `Property` SET `Value` = ? WHERE `Property` = 'ProductCode'"
Set view = database.OpenView(sqlQuery) : CheckError
Set record = installer.CreateRecord(1) : CheckError
record.StringData(1) = environments(i).getAttribute("productCode")
view.Execute record : CheckError
view.Close

sqlQuery = "UPDATE `Property` SET `Value` = ? WHERE `Property` = 'UpgradeCode'"
Set view = database.OpenView(sqlQuery) : CheckError
Set record = installer.CreateRecord(1) : CheckError
record.StringData(1) = environments(i).getAttribute("upgradeCode")
view.Execute record : CheckError
view.Close

sqlQuery = "UPDATE `Property` SET `Value` = ? WHERE `Property` = 'ProductName'"
Set view = database.OpenView(sqlQuery) : CheckError
Set record = installer.CreateRecord(1) : CheckError
record.StringData(1) = "porteco Processor [" + name + "]"
view.Execute record : CheckError
view.Close

database.Commit : CheckError
Dim cmd : cmd = "MsiInfo.exe " & databasePath & " /V " & environments(i).getAttribute("packageCode")
WshShell.Exec cmd
Wscript.Echo name & " environment installer built successfully"
Next

CheckError

Wscript.Echo ""
Wscript.Echo "All environments built successfully"

Wscript.Quit 0

Set view = Nothing
Set database = Nothing

Sub CheckError
Dim message, errRec
If Err = 0 Then Exit Sub
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
If Not installer Is Nothing Then
Set errRec = installer.LastErrorRecord
If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
End If
Wscript.Echo message
Wscript.Quit 2
End Sub
 
F

Felix Wang

Hi Mark,

Regarding the registry key issue, it seems to me that you have not changed
the Component ID of the component that holds the registry keys. As a
result, Windows Installer will increment the reference count for the
component. when we install a new instance of the service. The component
will not be removed until the reference count of the component reaches 0,
which is the last uninstallation of the service instances. Since the same
component holds different registry keys, Windows Installer cannot
differentiate them. It will only "remember" the registry keys hold by the
last installation of the component.

This issue is somewhat related to Windows Installer's component rules:

What happens if the component rules are broken?
http://msdn.microsoft.com/library/?url=/library/en-us/msi/setup/what_happens
_if_the_component_rules_are_broken.asp?frame=true

Have you had the opportunity to try Orca? We may use Orca to change the
component ID for the MSIs.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Thanks Felix

I will try modifying that in my script. I have been using Orca and used it to do all this manually to prove the concept and then scripted it so that it could be handed off to the configuration manager to do automatically. Other than that one glitch everything works perfect

Thanks again
Mark.
 
F

Felix Wang

Hi Mark,

If you have any concerns or new findings, please feel free to post here.

Have a nice day.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top