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

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.

Related

How can I use the ExportLogic command in EWL to deploy an application?

What exactly are the steps to take after running ExportLogic in the Package Manager Console? Does this do anything for updating the database on the server?
To deploy an EWL system using ExportLogic, the first step is to do a release build of your solution.
When that's done, run ExportLogic, which creates a Logic Packages folder in your solution's folder. Logic Packages will contain:
Server Side Logic folder - contains the files you need to put on the server for your system to run correctly, minus installation-specific config files
Client Side Application folder (if your system contains a client-side app) - contains the files needed to correctly run your system's client-side app, minus installation-specific config files
Copy the contents of Server Side Logic to your server, then create an Installation folder inside the Configuration folder and put your installation-specific config files in it.
If your system has a database, execute the portion of Configuration\Database Updates.sql that has not already been executed against your live database.
Finally, for each web application folder you copied to the server, create an IIS web site or virtual directory pointing to it.
If you're interested in automating some/all of these steps, there are APIs within EWL that may help.

C# App.config vs Settings File

This may sound like a trivial question, however I have looked over the web briefly and what I found was that app.config is basically an older mechanism for storing Application key/pairs of data for the application.
What I want to know is there any reason we (as .NET developers) would opt to use app.config over a Settings file ?
-Can someone please provide some pros and cons on both so we can use them properly.
thanks again
App.config for desktop applications and Web.config for web applications are part of .NET configuration system. Primarily they are used to control .NET framework settings in respect to our application. These are such configuration settings as substitutions of versions of assemblies (section <assemblyBinding>), substitution of .NET framework version (<startup>) etc. (see msdn for the full app.config schema.) One section is dedicated for custom settings of application developers (<appSettings>). There is also a possibility to create custom sections. So, when we need to store settings we can either piggy-back on the app.config or create our own separate configuration files.
Here are pros and contras of using app.config:
Pro: There is already a standard API in .NET to read settings from appSettings section. If you only need just a couple of config settings, it is much easier to use this ready API than to develop and test your own class to read your config files. Also, app.config file is already included in VS project for you.
Pro: There is a standard hierarchy of machine.config/app.config. If you plan such settings that can be set machine-wide and overridden or left as-is for individual applications, you should use app.config.
Pro/Con: App.config is cached in run-time. If you anticipate updates of it while your application is running, you need to specifically request refresh of certain section of config file. For web.config the web app is automatically restarted when something is changed in the file. This is quite convenient.
Con: app.config is stored in the same directory as your .exe file. Normally it will be in a subfolder of C:\Program Files. This directory is extra protected in Windows 7 from writing. You need to be member of Administrators group to write there and if your UAC (User Access Control) level in Control Panel is not set to 0 (which normally is not), you will be asked by the OS to confirm writing to c:\Program Files. So, users without Administrator rights will not be able to change configuration in app.config. Same goes for changing your settings programmatically: your application will get exception when attempts to write app.config if it runs not under an admin user on Windows 7. Your own config files usually go to C:\ProgramData\ or c:\Users subfolder (on Windows 7). These locations are friendlier to writing by users or programs.
Con: If user edited your app.config file and accidentally corrupted it, the whole application will not start with some obscure error message. If your separate config file is corrupted, you will be able to provide more detailed error message.
In conclusion: app.config gives you easier (faster development) approach, mostly suitable for read-only settings. Custom settings file gives you more freedom (where to store file, validation/error handling, more flexibility with its schema) but requires more work during development.
You have it backwards, the settings file (or ini file as they were originally called) was the mechanism used to hold application settings (key/value pairs) prior to Windows 95. With the release of Windows 95 it was recommended that application settings be moved into the Windows Registry (which proved problematic since if you screwed up your registry your Windows may no longer be able to start).
The .config file came into play with .Net. The XML format allows more dynamic and complex settings configurations than simple key/value pairs.
The modern user/settings file is an XML extension of the .config file (settings that can override certain settings in the .config under specific conditions).

C# app.config files and UAC

I started out with my application writing the config to the registry like I did years back with UAC wasn't around.
Turned out this wasn't a good idea so I moved to the app.config file and found that this is having issues as well with UAC.
The configuration I have for the application is machine specific; individual users do not have their own configuration and the rest of the apps including the service all drive off the single configuration file.
If I try updating this file in the program files\myapp folder it gets denied.
What is everyone else doing for a scenario like this where there needs to be a single configuration file?
I should also mention that this configuration needs to be updated from within my applications.
I would use the Common Application Data folder, this is where most new applications store data which works with UAC.
You can get this with the following code:
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
To view all options for special folders you can check this link:
http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx
The most common options would be the following:
Application Data - The directory that serves as a common repository for application-specific data for the current roaming user.
Common Application Data - The directory that serves as a common repository for application-specific data that is used by all users.
Local Application Data - The directory that serves as a common repository for application-specific data that is used by the current, non-roaming user.
You should be storing your users' settings in app.config you should be using user.config. Have a look here for more info.
Any machine-wide configuration files should be stored in:
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
Files in Program Files shouldn't be modified except when the application is installed/updated.
I had a similar need with a WPF application. What I do is the following:
Install the application with a boiler-plate configuration file.
When the app runs, it checks for a config file in the user's App Datadirectory for configuration files, if they're not present it copies the default boiler-plate config files from the install directory.
I then do any first-run initialization stuff that is needed.
I started out using the .NET ConfigurationManager, but I switched over to a plain old XML files because it was simpler and my requirements were basic.

Updates made to application config are only being read correctly in Windows 7 when the application runs as Administrator

We have an application that was built for the Windows Mobile and Windows platforms, using Visual Studio 2005. We have both versions of this application developed using a single code base to try and reduce code duplication. One of the issues that we encountered with this was that the ConfigurationManager was not available for the Windows Mobile platform. We worked around this by building our own ConfigurationManager that reads and writes settings to the "Application.exe.config" file in the Program Files folder. So both our Windows version and our Windows Mobile version use this same custom ConfigurationManager.
This worked fine on Windows XP and Windows Server 2003, but on Windows 7 we have encountered a problem and I don't know how to work around it. When we make a change to the config file (which we can only do by copying it to another folder, changing it and then copying it back... otherwise we get an "access denied" message when we try to save our changes directly in the Program Files folder), the change that we make is only reflected if we run the application as Administrator. If we run the application as a normal user, the default setting from the install are always shown. We suspect that this is a Windows 7 security-related issue, but can someone explain why this is happening? How can we change the settings so that they are also applied when the application is run as an ordinary user?
Windows 7 requires elevated privileges for several folders, including program files. It's not good practice to try to work around this.
Since you are using a custom solution, one option is placing your configuration file under %APPDATA%\yourproduct, which can be reached with
var appDataFolder = Path.Combine(Environment.SpecialFolder.ApplicationData, product);
A better solution is probably to use different configuration managers for different platforms, though. Couldn't some kind of abstract factory be applied?
I suspect your app tried to write to the config file at least once running non elevated and without a manifest. This made a "compatibility files" folder for your config file. When you run non elevated it looks there now. (See http://www.gregcons.com/KateBlog/FindingFilesYoureSureYouWrote.aspx for screenshots of how you can confirm this.)
If all you want is for a human, or some utility program you wrote that can run elevated, to be able to edit the config file, you can leave it where it is and put a manifest on your app to prevent virtualization. See http://www.gregcons.com/KateBlog/AddingAManifestToAVistaApplication.aspx for a sample manifest. That blog post goes on to tell you how to embed the manifest, but you don't need to, an external manifest will work. If your app is foo.exe, name the manifest foo.exe.manifest and put it in the same folder. This will prevent virtualization and cause the app to read the "real" config file.
If changing the config file will be a normal everyday occurrence, don't write the file under Program Files. AppData is a good choice.

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

Categories