VS.NET MSI Installer Screen Customization - c#

I've added two textbox screens to my MSI installer, and have a custom installer action that hooks back to the application I'm installing to save config settings to the app.config file.
My question is this:
Other than the MSI property screens that allow you to add default text to the MSI custom textboxes, is there a way to have the MSI grab values to put into the text fields from a file or web service, or something? I don't really want these values hard coded into the MSI property screens, and have to recompile and redistribute to change them.
I'd really like to just throw an XML, or CSV file in WITH the installer, and have it read them out of that file, but I haven't seen a way to do that.
Thank you.

With a custom action written in native code (C), you can do anything you want in an installer, as long as the user executing the MSI has permission to do so (which depends on whether it's the UI phase or the execute phase of the MSI - the latter is run by a system service).

What I eneded up doing was using GetPrivateProfileString from importing "kernel32" dll, and sticking a custom written INI file next to the MSI. The property screens I was trying to fill out were removed, and now I can deploy a custom INI file with settings on a per client basis, without having to recompile, and make tedious changes to the installer settings in the project. Email or contact me if you want me to post the code.

Related

How to allow for editable .Net generated config files with MSIX?

I am trying to help port a .Net service to a more modern .Net version (possibly Core) and use the MSIX installer. The application has several configuration files generated by the compiler (in source they are app.config but compiled they become *.exe.xml), they are installed into Program File right next to the binaries and a GUI helper app as well and the application itself can modify them to change service behavior (port, ip, tls cert, etc).
Writes under C:\Program Files\WindowsApps\package_name are not allowed.Writes under C:\Program Files\WindowsApps\package_name are not allowed.
The problem I am facing is that the MSIX installer makes it so that files in it's sandboxed version of Program Files cannot be written to (see above). That means that this application cannot be configured, so I am trying to figure out not only how to make the app configurable again, but also how windows wants to handle app configuration.
Right now it seems like there is two general approaches to do this:
write the configuration data to the service account's AppData/local folder
try to mimic a /etc/Myservice behavior in another folder. (meaning a local system-wide directory that houses configuration data for the service)
If you suggest #1 please answer the following additional questions:
How would I move Application configuration files to a user configuration file directory
how can an admin with a normal account modify the config file in the Service Account's AppData folder with the mentioned GUI helper application? (do they need to enable desktop access to the service account, login and run the GUI)?
If you suggest #2:
Where would you suggest this directory exist (specifically where will MSIX allow it)?
How do I tell the .Net application that the files are not right next to it? Can I just use AppData.CurrentDomain.SetData?
Well, a service running on the system account is the same for all users, so I would say that CommonApplicationData is a better folder for storing its settings, instead of appdata. This folder is easily accessible to both your service and to any admin that needs to deploy a custom config file.
In AppData you should store only actual user files (like files or settings generated by the actions taken inside your app by a specific user - thus different files for different users).
Now, the second part is where you need to configure you code to load the config file from a custom path instead of looking for it next to the EXE. I am no .NET expert but after a quick search I found this:
Relocating app.config file to a custom path
The modern approach to deploying app customizations
What is not clear to me is how your customers use the GUI helper tool to customize the config file. Is this just a tool that is used by someone from the IT department to generate the config file, and then they would copy that file and deploy it to the end-user machines using an MSI/MST file (or through some other custom deployment method)?
If your application is only deployed by IT folks, then you can try another simpler (and much elegant) solution for providing it with a custom config file, which actually doesn't require any code changes.
You can still leave the config file next to the EXE, in ProgramFiles and instruct the IT teams that deploy the app to use an MSIX Modification Package to deploy the custom config file generated by your GUI helper. (check the link included above for an example - with a video version at the end of the article).
Note: IT teams can use multiple free or paid tools to generate MSIX Modifications Packages.
Of course, your GUI helper tool still needs to generate that customized config file in a folder where it is allowed, as it can no longer write under ProgramFiles. So actually, you do need to modify a little bit your code in this scenario too.

C# WIX Uninstall Permanent File?

I am using a custom action during install to write a text file to my install directory. When I uninstall, that file is not removed nor is the corresponding install directory. However everything else is uninstalled properly.
I understand the reason that WIX cannot uninstall this file using the uninstaller, I'm just wondering what's the best way to call into a "clean up" action on uninstall which in which I can manually delete the directory/file?
You could include a RemoveFile element in whatever component your text file is most closely associated. When that component is uninstalled, the text file will be deleted as well.
<RemoveFile Id="CleanUpLogFile" On="uninstall" Name="log.txt"/>
You could install an empty text file and then have the custom action write to the file instead of creating it.
In general, I would suggest to stay away from custom actions as much as possible (they can get quite messy when dealing with install, uninstall, patching, repair, etc.) You may want to consider having your application itself configure the file on first run or have an additional configuration app that is executed on first run.
you can always run a console app for example that removes the file through code. You would just add that project only to the uninstall custom actions.
Out of curiosity what is the nature of the text file? In similar situations where the text file is an install log I'd recommend logging to a temp directory or a location that is not under Program Files (such as the Program/AppData folders - C:\ProgramData\Manufacturer\ on windows 7 for instance).
This approach bypasses this issue completely eliminating the need to create custom clean up scripts or actions.

How to copy a file that's in the same directory as the installer

I want to copy a file that's in the same directory as the installer file to the application directory. I can't include the file in the installer.
the scenario:
I create an installer for my client.
the client will distribute the installer to an unknown number of third parties,
these third parties will need to change an aspect of the configuration for the application.
they will subsequently distribute the installer with their edited config to an unknown number of end users.
The end users need to be able to just double click the installer, no knowledge on their part can be assumed.
I can't/don't want to create a separate installer for every third party that will distribute the application.
The solution I've come up with is letting these third parties add a config file to be distributed together with the installer. This file will be copied to the application dir on installation. I created a custom installer class for this purpose.
The part where I am stuck is how to find the file. All the provided methods to find the active assembly etc inside the installer class seem to point to a directory inside Window\system32, instead of the original directory where the installer was launched from.
Any help greatly appreciated.
Is this what you are after? You pass custom data to the custom action, using one of the built-in, but hard to find parameters available when you design setup projects in Visual Studio.
http://adamhouldsworth.blogspot.com/2010/01/get-msi-location-during-setup.html

Force overwrite of App.config during installation

We currently have 4 installers for our client software:
ClientSetupTest
ClientSetupProduction
ClientUpdateTest
ClientUpdateProduction
The only differences between them are that Setup contains the Crystal Reports redistributable files, and Update doesn't. Test and Production just specifies which environment they run in and the only difference there is one line in the Client.exe.config file.
Dumb, I know, which is why I replaced them all with one installer after getting rid of Crystal Reports. The new installer writes the selected environment out to setup.config, which is referenced by the file attribute (see here).
The "file" attribute is new to the config file with this new installer. The problem I'm running into is that if we modify the Client.exe.config file on an old installation, then run the new installer, the config file never gets updated with the "file" attribute.
Is there any way to force it to update a file? RemovePreviousVersions doesn't exactly work, since it's a different installer, unless I'm misunderstanding something. My current idea, which will probably work, is to add code in the OnBeforeInstall method to rename the old Client.exe.config to a backup file, so it'll always write the new one. Seems like there should be a simpler solution within the installer itself, though. Any ideas?
EDIT: Renaming the old config file to Client.exe.config.old before calling base.OnBeforeInstall() didn't work. It renamed the file, but never wrote the new one.
Windows Installer won't update a modified file.
Nonversioned Files are User Data—If the Modified date is later
than the Create date for the file on the computer, do not install
the file because user customizations would be deleted. If the Modified
and Create dates are the same, install the file. If the Create date
is later than the Modified date, the file is considered unmodified,
install the file.
You have some options:
include a custom action that modifies the file in place. This might be a script or .NET code.
do as you say - move the existing file out of the way. The installer won't stop on it. But you need to make sure it happens in the order you are imagining. You may need Orca to figure out the ordering.
include a custom option to set the create date to be "today". This should be really simple with a scripted custom action, using the Scripting.FileSystemObject. Then Windows installer will overwrite it.

I require a MSI Custom action that copies a file from the MSI source directory

I'm creating a installer for a c# windows project using VS 2008. I'm trying to write a custom action that copies a settings file from the source directory of the MSI file stored on a file server (e.g. \server\fileshare\myappinstaller\mysetting.xml) to the target directory on the computer on which my application is been installed (e.g. C:\Program Files\My App).
The settings file can't be added in to the installer as it will contain settings with will be unique to the customer installing the app.
Does anyone have code (preferably C# or VB.NET) for such a custom action? Alternately does anyone know how to get the MSI source location (e.g. \server\fileshare\myappinstaller) within a custom action.
Many thanks
I have solved this by adding
/InstallerPath="[OriginalDatabase]"
to the CustomActionData of the Custom Action (in the Tab Custom Actions of the Setup Project) and reading the value with this code in the Custom Action:
Public Overrides Sub Commit(ByVal savedState As System.Collections.IDictionary)
MyBase.Commit(savedState)
Dim directoryOfMSI As String = IO.Path.GetDirectoryName(Context.Parameters("InstallerPath"))
'Do your work here
'...
End Sub
Ciao!
Stefan
I would recommend you to add the XML file to the installer as one of the components to be installed. That would be the easiest way and would not require a custom action.
WiX might be an option for you. It allows you to customize XML configuration files during installation using XmlConfig.
I do a similar thing, but ship a default configuration inside the MSI file and then use a MST to add the custom configuration file. It's much more reliable as everything is "native" to windows installer and I just need to send out a small custom MST to each customer.
More information on how I'm doing this can be found over at Simplest solution to replace a tiny file inside an MSI?
Normally custom actions in WindowsInstaller use something from the tables of the msi to put something into any table of the msi.
Additionally the WindowsInstaller-Team declines any managed extensions for the installers, reasons for that are found everywhere on the net.
But, I did some time ago figure out an extension to create managed custom actions for WindowsInstallers, usable with WiX, that works still, but there is a newer solution on top of that work, a real extension for WiX to allow managed custom actions.

Categories