Custom ClickOnce installation path - c#

Is there a way to set the ClickOnce client installation folder to something static like "...\%User%\Appdata\Local\%MyProgram%?
Detailed info:
I am using ClickOnce to distribute an intranet application. Everything works fine, and the application installs and updates like it should. The one issue I am running into is one of the modules in the application moves files from one folder to another folder. The end user has Trend Micro installed, and the application was getting nuked and quarantined every time the module ran. I had the IT department whitelist the application, but due to the random installation path below "...\AppData\Local\Apps\2.0...", and because Trend Micro can't handle the '.' in 2.0, they were having to whitelist the executable below the "\Local\Apps\" folder, which they weren't comfortable doing. Is there a way to change the ClickOnce installation folder to something like "...\%User%\Appdata\Local\%MyProgram%?

Simple answer: no you cannot change that path, it is a key part of the sandboxing that is a feature of ClickOnce.
Even with custom manipulation and re-signing of the ClickOnce manifests you cannot alter that path (this is one of the ways that ClickOnce allows you to have multiple published instances installed on your machine even if they are the same version).
I'd suggest that before packaging (i.e. as part of your release build process) you sign your binaries with a code signing certificate from Verisign or similar - anti virus products typically use this as an indicator of whether something can be trusted. If that fails to solve the problem then look at whether you can whitelist based on the file name rather than the file path.

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.

Issue Related to Read only DB file after installation

I have an Application in WinForms,
I have created SetupDevelopment project and then install an application using Setup.exe file
i have added MSAcceess db file into application folder file,
when i install an application the database file gets readonly. how can i make file writtable after installation?
I found some solution on internet and found that when i tried to install application in different path other than "C:\ProgramFile\" and make application available to all user,it solves my Problem, but i want to install an application only in "C:\ProgramFile\" and want to available to only "Current user"
how can i achieve my Problem ?
In modern Windows Operating System the folders 'Program Files' or 'Program Files (x86)' are read only for the common users. This choice has been done for security reasons and you cannot easily bypass this rule. The reccomended folders, to use just for the current user, are C:\users\username\AppData\Roaming or C:\users\username\AppData\Local identified by the Environment.SpecialFolder.ApplicationData or Environment.SpecialFolder.LocalApplicationData. To this base folders add another subfolder identifying your application or company and install your database there.
If you want your database available to all users of the current PC, you could install it in the Environment.SpecialFolder.CommonApplicationData that resolves to C:\programdata. (Again, adding a subfolder specific for your application or company)
Again, don't try to force the operating system to work against its rules. You will find yourself in trouble very often.

What target folder should I install my application to that will never require uac elevation?

I have an app and I am working on the installer for it. Assuming that I want the installation to not require elevation and I want the application itself to never require elevation and I want the updater for the application (which is build in) to never require elevation where should I install the application to?
Caveats:
This application is not signed.
I am okay if each user has to install it separately under their profile.
Can I use the registry in the install and accomplish the same goal?
The only writes it makes are to setttings/configuration files.
.NET 4 app.
A common choice is the local appdata folder returned by SHGetFolderPath(CSIDL_LOCAL_APPDATA) (Win2K and later) or SHGetKnownFolderPath(FOLDERID_LocalAppData) (Vista and later).
This returned path is something like:
"C:\Users\arx\AppData\Local" (Vista and later)
"C:\Documents and Settings\arx\Local Settings\Application Data" (pre-Vista)
It's normal to create company name and application folders under here, so you'll finish up with a path like:
"C:\Users\arx\AppData\Local\BlahSoft\BlahApplication"
Update
If you want this path from .Net you need Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
Your question is tagged both WIX and .NET; the two have different syntaxes for known-folder paths. The .NET command to get the current user application folder is Environment.GetFolderPath(Environment.SpecialFolder.Programs).
If you want to install to a WIX path, it has predefined properties for each known folder; [ProgramFilesFolder] is to the 32-bit application folder and [ProgramFiles64Folder] is to the 64-bit folder.

Determining location of a Clickonce application within Clickonce Cache

I have an application deployed via ClickOnce, along with a separate .NET console application that needs access to the ClickOnce application's installation directory. By the application's installation directory, I mean:
"C:\Documents and Settings\[username]\Local Settings\Apps\2.0\[obfuscated folder]\[obfuscated folder]\[obfuscated folder]\application.exe"
, or on Windows 7:
"C:\Users\[username]\AppData\Local\Apps\2.0\[obfuscated folder]\[obfuscated folder]\[obfuscated folder]\application.exe"
Is there any way for me to generate, or preferably determine at build time, what the obfuscated folder names will be for my application?
Basically, I would like for the console application, which is built and distributed with each release of the application, to know the directory structure under which the application will be installed.
I know that I can determine this location from within the ClickOnce application using "Application.ExecutablePath", and then save the value to a known location, but I would much rather be able to predict the application's installation path in advance...
Any ideas?
I don't think its possible to know that path in advance. It can also change when you update the version of an app too.
Do you want to know the path so that the two apps can find each other? If so you could use a simple IP listener in one app and connect to it from the other one. You can just connect on 127.0.0.1 and then ask the other app the path.

What is the best way for on demand download and install of dlls in .NET?

We have an application that we wish to install just a basic shell for. As the users use it, it will download and install the necessary dlls for actions that need to take place (imagine a wizard application scenario with several possible paths). Currently, everything is installed for all possible paths through the shell app.
For about 3 months out of the year, the dlls used for the possible paths go through a high churn rate with updates, so we wish to start ensuring the users have the most recent version of these dlls. The idea is that after all their selections are made, we'd make a web check to see what dlls are required for their selection and check to make sure they have the most recent version of those files.
All of this we have a plan for on how to do it. The problem I'm fighting is what is the most appropriate way to "install" these files. ClickOnce is not an option...too much legacy stuff here. Our app is installed in "Program Files" which obviously has restrictions for writing random files into the program's install folder under Vista and later.
Right now I see the options as the following:
On install mark the install directory as writable for the "Everyone" group. I haven't actually tested to see if this would work yet, or if Vista does something different in this scenario.
Split the download portion out into a second app that we can have prompt for elevated privileges so that it can download and install these files.
I'm leaning towards the second option since that maintains the security aspect of the Program Files folder. Others in the group lean towards the first option because they just don't want to have to worry about things. Or is there some other option I'm missing?
The app is a .NET app, though it has some requirements of third party dlls that are not managed assemblies.
As long as the dlls you want to load are managed, there are several ways to do this.
One way is to designate an Environment.SpecialFolder path such as AppData and dynamically load assemblies into your appdomain from there. RssBandit does this for plugins, there is a special directory that loads dlls and searches for specific interface implementations, loads them into a temporary appdomain, and then calls them from the app. You could take this one step further by using an IoC library like ninject or structuremap.
you could also try MEF, the new extensibility framework coming out in C# 4.
Personally, I like what Firefox/xul apps do. It's a hybrid of your two proposed solutions, I suppose. They have an updater.exe that lives in the install directory. I assume that means that the install directory is made writable during install so that they can run the update application. However, having never deployed a application in this manner, I can't tell you how much of a headache (or not) it is.
An alternative which you haven't mentioned, and may not know about, is using the .Net download cache. When you attempt to load an assembly you can give it a code base to load from. If you set the codebase to a web url (i.e. http://mywebhost/mycoolapp/) .Net will download the assembly from that url if it's not found in the download cache. It will also grab the latest version of the assembly from the web url if there is one.
This approach can be a pain as you'll likely have to deal with CAS security issues if your app needs elevated permissions. However, it is nice not having to write code to download the latest versions of your assemblies for you. If you want more information, I can find some resources and give more detailed examples.
The way I handle it is to have an update.exe installed into program files next to the main .exe file.
Then, on app startup, I have the app download an xml file off of the web and save it in the App Data folder. This file contains the latest versions of the dlls and has a simple Filename, Version structure.
Run through the list of filenames and if you don't have the dll locally or you have an older version, then add the needed dll to an update list.
After you generate your update list. Fire off the Updater.exe with a command line list of the files to be updated. You don't have to write them to program files but I do. On Vista, my updater pops up the UAC prompt correctly (as it should to maintain Program Files' security).
The updater then downloads the files to Program Files and restarts the main app.
One problem with firing off the second app is that you have to give it a manifest with "AsAdministrator" set in it.
This isn't hard to do, but once the updater is done and retriggers the main app, it cannot start the main app with normal privileges. An exe running as administrator can only start other exe's as administrator also, even if "AsInvoker" is set in the manifest. I don't know why you can't restrict it back to normal rights...you can only elevate permissions for some reason...

Categories