PDA

View Full Version : .NET service: setting configuration file settings at install time



jonathanqis
09-21-2012, 06:50 AM
I wish to install a service A.exe in my install and set settings in it's acompanying A.exe.config file during the installation.

I have tried including the files as:
1. One component with the A.exe as the key file.
2. Two separate components.

When I set the service components '.Net Settings\.Net Installer Class to:
NO
The installation succeeds and the service can be started/stopped successfully.

However, the service (A.exe) contains a .NET (C#) class derived from 'System.Configuration.Install.Installer' and has the
public override void Install(IDictionary stateSaver) method implemented with default code
base.Install(stateSaver);

When I set to service components '.Net Settings\.Net Installer Class to:
YES
The installation fails, reporting error 1001 twice.

It seems to make no difference If I modify the .NET Installer Class arguments.

Here are what I believe to be the significant differences from log files of the two install attempts. These differences being in the one that failed.


Action start 12:10:16: StartServices.
MSI (s) (44:84) [12:10:16:897]: Doing action: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit.SetProperty
Action ended 12:10:16: StartServices. Return value 1.
MSI (s) (44:84) [12:10:16:897]: PROPERTY CHANGE: Adding _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit property. Its value is '/installtype=notransaction /action=commit "C:\Program Files (x86)\QiSOFT\InstallClass\AlarmNotifier.exe" "C:\Users\JONATH~1.QIS\AppData\Local\Temp\{A895018C-84B8-4472-9FC7-7A5CE127D1E0}\_isconfig.xml"'.
Action start 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit.SetProperty.
MSI (s) (44:84) [12:10:16:897]: Doing action: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit
Action ended 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit.SetProperty. Return value 1.
Action start 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit.
MSI (s) (44:84) [12:10:16:901]: Doing action: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback.SetProperty
Action ended 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit. Return value 1.
MSI (s) (44:84) [12:10:16:902]: PROPERTY CHANGE: Adding _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback property. Its value is '/installtype=notransaction /action=rollback "C:\Program Files (x86)\QiSOFT\InstallClass\AlarmNotifier.exe" "C:\Users\JONATH~1.QIS\AppData\Local\Temp\{A895018C-84B8-4472-9FC7-7A5CE127D1E0}\_isconfig.xml"'.
Action start 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback.SetProperty.
MSI (s) (44:84) [12:10:16:902]: Doing action: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback
Action ended 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback.SetProperty. Return value 1.
Action start 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback.
MSI (s) (44:84) [12:10:16:906]: Doing action: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install.SetProperty
Action ended 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback. Return value 1.
MSI (s) (44:84) [12:10:16:907]: PROPERTY CHANGE: Adding _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install property. Its value is '/installtype=notransaction /action=install /targetDir="C:\Program Files (x86)\QiSOFT\InstallClass\" /dbServer="JONATHAN2010\QISOFT2008" /dbCatalog="Q6TestNew" "C:\Program Files (x86)\QiSOFT\InstallClass\AlarmNotifier.exe" "C:\Users\JONATH~1.QIS\AppData\Local\Temp\{A895018C-84B8-4472-9FC7-7A5CE127D1E0}\_isconfig.xml"'.
Action start 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install.SetProperty.
MSI (s) (44:84) [12:10:16:907]: Doing action: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install
Action ended 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install.SetProperty. Return value 1.
Action start 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install.
MSI (s) (44:84) [12:10:16:911]: Doing action: ISSQLServerInstall
Action ended 12:10:16: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install. Return value 1.


and later


MSI (s) (44:84) [12:10:18:711]: Executing op: ActionStart(Name=_4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit,,)
MSI (s) (44:84) [12:10:18:711]: Executing op: CustomActionSchedule(Action=_4ADE5C0E689DCA80CF624E5C0BE5D3F8.commit,ActionType=3585,Source=BinaryData,Target=ManagedInstall,CustomActionData=/installtype=notransaction /action=commit "C:\Program Files (x86)\QiSOFT\InstallClass\AlarmNotifier.exe" "C:\Users\JONATH~1.QIS\AppData\Local\Temp\{A895018C-84B8-4472-9FC7-7A5CE127D1E0}\_isconfig.xml")
MSI (s) (44:84) [12:10:18:711]: Executing op: ActionStart(Name=_4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback,,)
MSI (s) (44:84) [12:10:18:712]: Executing op: CustomActionSchedule(Action=_4ADE5C0E689DCA80CF624E5C0BE5D3F8.rollback,ActionType=3329,Source=BinaryData,Target=ManagedInstall,CustomActionData=/installtype=notransaction /action=rollback "C:\Program Files (x86)\QiSOFT\InstallClass\AlarmNotifier.exe" "C:\Users\JONATH~1.QIS\AppData\Local\Temp\{A895018C-84B8-4472-9FC7-7A5CE127D1E0}\_isconfig.xml")
MSI (s) (44:84) [12:10:18:712]: Executing op: ActionStart(Name=_4ADE5C0E689DCA80CF624E5C0BE5D3F8.install,,)
MSI (s) (44:84) [12:10:18:712]: Executing op: CustomActionSchedule(Action=_4ADE5C0E689DCA80CF624E5C0BE5D3F8.install,ActionType=3073,Source=BinaryData,Target=ManagedInstall,CustomActionData=/installtype=notransaction /action=install /targetDir="C:\Program Files (x86)\QiSOFT\InstallClass\" /dbServer="JONATHAN2010\QISOFT2008" /dbCatalog="Q6TestNew" "C:\Program Files (x86)\QiSOFT\InstallClass\AlarmNotifier.exe" "C:\Users\JONATH~1.QIS\AppData\Local\Temp\{A895018C-84B8-4472-9FC7-7A5CE127D1E0}\_isconfig.xml")
MSI (s) (44:0C) [12:10:18:745]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIF4C9.tmp, Entrypoint: ManagedInstall
MSI (s) (44:64) [12:10:18:745]: Generating random cookie.
MSI (s) (44:64) [12:10:18:746]: Created Custom Action Server with PID 7744 (0x1E40).
MSI (s) (44:60) [12:10:18:768]: Running as a service.
MSI (s) (44:60) [12:10:18:769]: Hello, I'm your 32bit Elevated custom action server.
MSI (s) (44!48) [12:10:25:177]:
MSI (s) (44:0C) [12:10:25:178]: Leaked MSIHANDLE (163) of type 790531 for thread 7752
MSI (s) (44:0C) [12:10:25:178]: Note: 1: 2769 2: _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install 3: 1
Info 2769. Custom Action _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install did not close 1 MSIHANDLEs.
CustomAction _4ADE5C0E689DCA80CF624E5C0BE5D3F8.install returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)


Guess I need to know why it failed to close the MSIHANDLE ?

N.B. I am on a Windows 7 64Bit system but the application is a 32bit one and I have no other problems with installing it or its components on this system as a 32bit app.

I have also tested on a 32bit virtual machine and it fails in exactly the same way.

I had no problem doing the same thing for a .Net dll.

Does anyone have experience of using the .NET Settings to do this with a .NET service executable ?

Any one got an example or ideas about what I may be missing?

Help appreciated.

Christopher Painter
09-21-2012, 09:18 PM
Using Installer class custom actions to install services is reinventing the wheel with a more fragile solution. Dump it and use the ServiceInstall / ServiceControl tables instead. As for the config file settings, App.Config files are XML files and you can use the XML Changes view to declare the XPath needed to update the file.

InstallShield will create the directories, lay the files down, update the config file, create the service and start the service and you don't have to write a lick of code to make it happen.

jonathanqis
09-24-2012, 03:13 AM
I am already using the InstallShield component properties to declare the service and control its installation and uninstallation.

I am trying to use InstallShields documented mechanism to invoke the (System.Configuration.Install.Installer) windows .NET class functionality.
This is a more flexible and capable mechanism to do actions during the various stages of installations.

The help item Reading Properties Passed to the .NET Installer Class gives a code example for the Installer class which I have tried to use.


This is the base class for all custom installers in the .NET Framework. Installers are components that help install applications on a computer.
Microsoft.

I wish to use the documented mechanisms and to resolve issues that they may have.

I would appreciate any help in resolving the original issue, which appears to be an unsuccessful attemp by InstallShield to action the Installer class calls on the .NET assembly.

N.B. I have already tried this action on a test file (.dll) and it worked just fine. A significant difference here is that the file containing my deriver Installer class is an executable file (.exe).

Perhaps someone from InstallShield would like to clarify the use of this option and any restrictions that apply.

Christopher Painter
09-24-2012, 06:19 AM
I am already using the InstallShield component properties to declare the service and control its installation and uninstallation.

I am trying to use InstallShields documented mechanism to invoke the (System.Configuration.Install.Installer) windows .NET class functionality.
This is a more flexible and capable mechanism to do actions during the various stages of installations.


I assure you that this is *NOT* a more flexible and capable mechanism. It's probably one of the worst parts of the .NET Framework Base Class Libraries.

http://blog.deploymentengineering.com/2006/07/msi-vs-net.html

FWIW, I've been authoring installers for 16 years now. My 4000+ posts on this forum are a testament to my interest in this space. You can take it to the bank when I tell you to dump the custom action and to use the XML Changes view instead.

jonathanqis
09-25-2012, 08:00 AM
I took a look at the xml replacement idea.

It would also be good if the entry under the XML view could be tied to a file by component Id rather than a string identifier. Would make it less prone to be broken by changing file names etc at a later date. (I get this for free in the installer class :D)

I don't yet see a mechanism to do this replacement.
But the rest looks promising.

Christopher Painter
09-25-2012, 08:29 AM
MSI uses [] to reference the value of a property. [SOMEPUBLICPROPERTY] is what you would use.

The XML Changes are tied to the component. At the bottom of the screen you'll see it say "Component Name: xxx" with a hyperlink to the component. By tied I mean if the component is getting installed the changes are processed. Some MSI tables assume the file to be the keyfile of the component ( advertised shortcuts, services ) but in this case the changes can be applied to other XML files and hence the need for the file name. The string table entry is only so that the filename can be localized for different languages. (An additional layer of abstraction.)

XML Changes are a little difficult to get used to since you have to provide all the correct XPath statements but there is a "test xml changes" feature (right click the file to access the menu option ) that helps get it right without building over and over.