3

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:

  1. write the configuration data to the service account's AppData/local folder
  2. 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:

  1. How would I move Application configuration files to a user configuration file directory
  2. 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:

  1. Where would you suggest this directory exist (specifically where will MSIX allow it)?
  2. How do I tell the .Net application that the files are not right next to it? Can I just use AppData.CurrentDomain.SetData?
Liam Kelly
  • 3,524
  • 1
  • 17
  • 41
  • It's not about MSIX. The application's files shouldn't be editable, whether they're stored in `Program Files` or wherever UWP applications are stored. Windows enforces this since the 1990s by making `Program Files` read-only. In later versions, attempts by misbehaving applications to write there are redirected to other folders. – Panagiotis Kanavos Dec 15 '20 at 14:16
  • Editable config files are never stored in the application's folder, whether `Program Files` or wherever UWP applications are stored. In *all* cases, applications should store their editable data under `%APPDATA%` or `%LOCALAPPDATA%` for common settings, or `%USERAPPDATA%` for user-specific data. The actual special folder path can be retrieved with [Environment.GetFolderPath](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getfolderpath?view=net-5.0) – Panagiotis Kanavos Dec 15 '20 at 14:18
  • This means that nothing changed. No application could be configured by overwriting its `exe.config` to begin with. Even applications that thought they did so, were redirected by the OS itself. Since you use ASP.NET Core, you can easily store settings files wherever you want and have them override the settings stored alongside the application – Panagiotis Kanavos Dec 15 '20 at 14:31

1 Answers1

2

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:

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.

Bogdan Mitrache
  • 10,536
  • 19
  • 34
  • 1
    .NET Core has no `.config` file, it can load settings from multiple providers (including databases, environment variables etc), stored in any path accessible by the executing account. Storing data in `CommonApplicationData` is now as easy as using the correct path. Providers can override previous settings, so no transformations or customizations are needed – Panagiotis Kanavos Dec 15 '20 at 14:27
  • @PanagiotisKanavos is this config wrangling all handled by the `AppDomain` API for every .Net version? – Liam Kelly Dec 16 '20 at 13:51
  • 1
    @LiamKelly it doesn't matter because you shouldn't be trying to write to `exe.config` in the first place. Besides, ASP.NET Core *has no .config files*. You don't need to modify anything, just save the extra settings in a writable location and make sure you load it *after* the providers you want to override. Given the defaults, (appsettings.json, appsettings.{env}.json, evn variables, command line), simply using `AddJsonFile` pointing to a JSON file in `CommonApplicationData` can override previous settings. Just as `appsettings.Production.json` overrides `appsettings.json` – Panagiotis Kanavos Dec 16 '20 at 13:55