User settings reset when the application is moved - c#

I've noticed that if you move that application .exe file in another location the user settings reset.
In my understanding this happens because the location in the app data folder is based on the path of the .exe as well, which is taken into consideration when the hash is being generated.
I know there are different alternatives, either by using the registry or by creating manually a custom config file, but my question is, is it possible to retain the user settings when the application (.exe) is moved to another location with the default functionality Microsoft provides ?
For my tests I use a standalone application (one .exe file only). Simply moving the file to, lets say /Desktop/Test/ from /Desktop/ causes a new folder to be generated under C:\Users\<user>\AppData\Local\<company>\Appname_Url_<hash> with the default user.config in it. The old user.config is still available so if you move the .exe file back to its previous location then the previous settings get loaded again. This becomes troublesome not only because you lose the settings, but if you move the file 10 times in 10 different locations you end up with 10 new folders in the appdata.

This is in fact a security feature, related to assembly deployment and clickonce stuff.
I think you just need to add a strong name to the main assembly to overcome this issue.
If you don't have a strong name, the name will be something like this and it will change if the application path change (see the Url token):
%appdata%\WindowsFormsApplication1\WindowsFormsApplication1._Url_3pei3cdnq3srqpjiwh1qnf12ncsp5c2w\1.0.0.0\user.config
If you have a strong name it will be something like this and it will not change because your app origin is now identified, whatever its current location is (see the StrongName token):
%appdata%\WindowsFormsApplication1\WindowsFormsApplication1._StrongName_fe0ndyau2vlgeac4gmbg13u3q4jtyrqv\1.0.0.0\user.config

From this blog post, regarding the location of the configuration file:
If you need to store the settings in a different location for some
reason, the recommended way is to write your own SettingsProvider.
Which tells me that with a little bit of code, you could probably store the file right where you want it, and it won't move.

Related

Update user settings from outside the application

I have a C# application (a VSTO office addin) running on clients' machines, and I need to make a setup project or any other EXE that can overwrite and update the user settings in the user.config files with my own values.
It seems that I can't know exactly where the user.config is- it seems to create different folders under AppData\Local\Microsoft_Corporation with different names and numbers. I can try to iterate every subfolder I find but I was hoping for something better.
I can't get the path by using ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal) because I'm not inside the application, and I tried it inside the application and it actually returned a different, wrong path.
I can overwrite the app.config because I know where the application sits, from the registry, but overwriting it doesn't change user settings if the user settings were already saved in user.config too.
Can I force .NET to write the user.config into a predetermined location and store it in the registry, so I would have it for my setup?
Any ideas how to complete this objective? Is there some common practice for this? Thank you
Don't update the settings from your installer. The installer can save new options locally (HKLM, local folder, etc.) visible to every local user. When your addin is loaded, it can grab the new settings from that location and update its local settings as necessary.

How to load a config file based on user selection from "unknown" location

I have searched and searched and can't find a solution to my specific problem. I am updating a console app that will now be used for more than one client. We have decided, over storing the info in a db at least for now, to store the clients info in config files. Each client will have their own configuration file. I need to know how to load a/any config file from an "unknown" location. All of the examples that I found want me to put in the path of the file. While using my computer, I will know the path, but once it gets pushed to other servers, the paths to the file will change.
Working under these conditions, how can I load a config file for any client without knowing the path to the file?
EDIT: The console app is only ran on one server, but it is used to go to different clients websites and crawl their site. This is why each client has their own config file. It contains the information needed to get and use their site. We have a task set up for the app to run each client on a timer.
Since everything was being read from the bin folder, I looked at the properties and changed from Do Not Copy to Copy Always for Copy to Output Directory. Now it WILL locate the config files in the bin folder. And the answer to this question put me in the direction to read my config files.
What about writing every piece of code with in mind that it is to be used in another file, say with an include statement. So, every file is used in another one until we reach a wrapper file, which only purpose is to define the location of the config file. The application would always be called through such a wrapper file. This wrapper file will do whatever necessary to determine the location of the config file and make it available to the included files. If it knows the user, it can look up in a table. The key point here is that, the wrapper files would not move when you move the code from one environment to another. I think that this is a useful feature, because we do not want edit the code each time that we move it from one environment to another. Another advantage of this approach is that it applies to all environments, even very limited environments. For example, let say you provide only a folder to a programmer as a sandbox to experiment with the code. This programmer does not have access to the /bin or the /etc directory. In contrast, the proposed approach will work fine in this case, because the programmer can set the config files wherever he wants in its local wrapper files. This issue is discussed here How to organize code so that we can move and update it without having to edit the location of the configuration file?

C# ClickOnce install folder - how windows generate the folder names

I would like to know how Windows generate folder, where will be ClickOnce application installed.
In Startmenu is "shortcut" to file, what is putted in some "startrek" folder like:
C:\Users\USERNAME\AppData\Local\Apps\2.0\GT??4KXX.PRJ\EGV???1G.??C\prin..tion_7???5a2?????74b6_0000.0002_1dae????89111c35
What does those folder names mean?
For example:
If i will have for example some settings.txt file where i want that user can change some parameters of the application. Is there way how to know, WHERE it will be installed and WHERE the file is? (Where user will find this settings.txt file).
I know that i can create the file for example in C:\ and after start the application i will modify the file in "strong" path. But i dont really like too much files, folders, whatever in C:\ and i prefer to have settings files in same folder like the application. But with ClickOnce installations is it really hard - impossible - to find that file.
It seems like when the "startrek" is something like hash of the project.
So i would like to know what does the folder means and if its some hash of the project or what is that.
To find the folder that contains your executable, you can use the Assembly.Location property.
For example:
string exeFolder = System.Reflection.Assembly.GetExecutingAssembly().Location;
However, if you want to store settings for your ClickOnce app, you shouldn't do it by writing a file to the .exe's folder.
Instead, you should use Microsoft's Application Settings support. Doing it any other way is going to be a lot of extra hassle, and Microsoft's support is very good. It does need half an hour to read through the documentation, but it's far and away the best thing to do, IMHO.
(I'm assuming that you only need the settings to be stored on the local PC for the same user to use later. If you want the settings to follow the user around (i.e. roaming settings), you can't use the Microsoft support.)
If you have more complex settings that you want to store in a file that you create directly, you should consider using the isolated storage that the answer from JRoughan mentions.
From inside the ClickOnce app you can find the default directory where files are stored using
ApplicationDeployment.CurrentDeployment.DataDirectory
Or you can use isolated storage and choose whether you want to save per application or per user.
I don't think it's possible to determine these folders from outside the app itself. If you need a known location you'll have to hard-code it.
Update
I also don't believe it's possible to infer what the install directory will be for an app. It would be unwise to use even if possible as updates to the app will not be in the same location.
If you have data that the user is modifying through your program, you will be happier if you don't leave it in the ClickOnce program directory. You can get completely messed up when there's an update. Check out this article about what to do with your data to keep it safe and be able to find it. It talks about putting it in LocalApplicationData, but if you want your user to be able to find it and edit it, just put it in MyDocuments/yourappname/settings or something like that.
I wouldn't use Isolated Storage; there are reported problems with that and ClickOnce.

single exe with changeable settings

I am trying to make a simple application which will be used to point a web browser control to some of our web applications at my work. I would like to have only one exe file but also have an admin window to change some of the settings and have them persist when the application is closed. Is that possible? I have looked at the application settings resources part but as I understand that makes a file that loads the settings.
I don't want to have to parse a file or have anything but ONE file so please don't suggest doing that if it is possible.
Just use application settings - that will create a single file, you won't have to do any parsing, it'll all be fine.
It'll be separate to the exe file, but unless you meant that "ONE file" to include the executable and rewrite that on the fly, it should fit your description easily.
For example, let's build a console app that just remembers how many times it's been launched:
Create a new console application project
Go to the properties page, and click into the Settings tab.
Click on the link to create a settings file
Type in the table to create a setting called "LaunchCount" of type int. Make it either user scope or application scope, depending on whether you want it to be persisted per user or system-wide.
Hit Ctrl-S to save.
In the Main method in Program.cs, write this code:
Settings settings = Settings.Default;
settings.LaunchCount++;
Console.WriteLine("Launch count: {0}", settings.LaunchCount);
settings.Save();
Add the appropriate using directive for Settings (put the cursor in Settings and hit Ctrl-.)
Run the app several times, and observe the number increasing.
You can't have persisted settings without having a separate file...safely. You must either have a separate file, which is the standard and suggested approach approach, like the one created with Application settings, or you must use something like the registry to save settings.
Keep in mind, though, that using the registry is highly discouraged due to security reasons. Plus most companies don't allow access to registries anyway which means that anyone without this access could not use the settings feature.
There are several ways to do this. You can use a command-line argument to do that. Launch the app from the shell and put in your command line argument and change how it launches.
A UNIX-y approach is to look at the name of the exe and change behavior based on that. If I recall correctly, rsh and rlogin are the same executable - they just look at argv[0] to decide how to run. In windows, this is straight forward - look at System.Environment.GetCommandLineArgs - if there is a non-empty string in the 0th element of that, it will be your executable name.
For persisting settings, see Jon Skeet's answer.
I have to say that this is generally a bad idea, but I've done this before a long time ago in VB6. I created a Resource within the exe and then (somehow) directly manipulated it.
The problem is, is that this is usually not possible within the .NET framework due to it being memory resident. These guys tryed it out in .net and they ended up creating an program in IL to do the heavy lifting... Modify Emdeded String in C# compiled exe
Go with a settings file as Jon suggested!

Best place to store configuration files and log files on Windows for my program?

I need to store log files and configuration files for my application. Where is the best place to store them?
Right now, I'm just using the current directory, which ends up putting them in the Program Files directory where my program lives.
The log files will probably be accessed by the user somewhat regularly, so %APPDATA% seems a little hard to get to.
Is a directory under %USERPROFILE%\My Documents the best? It needs to work for all versions of Windows, from 2000 forward.
If you're not using ConfigurationManager to manage your application and user settings, you should be. The configuration toolkit in the .NET Framework is remarkably well thought out, and the Visual Studio tools that interoperate with it are too.
The default behavior of ConfigurationManager puts both invariant (application) and modifiable (user) settings in the right places: the application settings go in the application folder, and the user settings go in System.Environment.SpecialFolder.LocalApplicationData. It works properly under all versions of Windows that support .NET.
As for log files, System.Environment.SpecialFolder.LocalApplicationData is generally the place that you want to put them, because it's guaranteed to be user-writeable.
There are certainly cases where you wouldn't - for instance, if you want to write files to a network share so that you easily can access them remotely. There's a pretty wide range of ways to implement that, but most of them start with creating an application setting that contains the path to the shared folder. All of them involve administration.
I have a couple of complaints about ConfigurationManager and the VS tools: there needs to be better high-level documentation than there is, and better documentation of the VS-generated Settings class. The mechanism by which the app.config file turns into the application configuration file in the target build directory is opaque (and the source of one of the most frequently asked questions of all: "what happened to my connection string?"). And if there's a way of creating settings that don't have default values, I haven't found it.
Note: You can get the path to the LocalApplicationData folder in .NET by using the following function:
string strPath=System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
For application settings - use System.Environment.SpecialFolder.ApplicationData - this is where a roaming profile data is stored, so it allows your user to log and work from different machines in the domain.
For log files - System.Environment.SpecialFolder.LocalApplicationData
The accepted answer notes that for log files the following is a good spot.
System.Environment.SpecialFolder.LocalApplicationData This equates to a path of C:\Users\[User]\AppData\Roaming which you can see is user specific. Like the accepted answer mentions this is a guaranteed user-writeable location and can be useful for certain situations
However in a web application environment you may be running your application under a network account and you or a coworker may need to try and track down where exactly those logs are going per application. I personally like to use the non user specific location enumeration of
System.Environment.SpecialFolder.CommonApplicationData which equates to C:\ProgramData. Yes, you will need to specify access rights for any folders you create, but it's usually a one time deal and then all of your application logs can live in one happy location.
Additionally, while looking around the Internet, there is a project out there to programatically set write access to folders you create within CommonApplicationData, Allow write/modify access to CommonApplicationData.
To be honest %appdata% is still the best place to place your config files and log files, as it serves the purpose of a placeholder to store your application data. It should not be that hard to access, just write %appdata% in explorer and you will be directed straight to your %appdata% directory.
Do not store config files in the application folder, Microsoft has stated this is NOT the ideal location. Windows has been moving towards blocking writing to C:\Program Files\ and you'll find in Vista any application that tries to write here, will fire up a UAC warning.
Windows 7 will allow users to customize what UAC popups they use (expect some power users to block most of them) and your app will fail/freeze if the user never approves this write attempt.
If you use the proper userprofile and appdata variables, then Win 2000, XP, Vista, and Win7 will map the data to the proper write friendly folder, with no UAC popups.
You can use SHGetSpecialFolderPath:
int MAX_PATH = 255;
CString m_strMyPath;
SHGetSpecialFolderPath(NULL, m_strMyPath.GetBuffer(MAX_PATH), CSIDL_COMMON_APPDATA, TRUE);
This will specify the 'special folder path' which you can safely write logs to for windows:
For XP: C:\Documents and Settings\All Users\Application Data
For Vista: C:\ProgramData
Check the MSDN page here: http://msdn.microsoft.com/en-us/library/bb762204(VS.85).aspx
The best answer depends on the nature of the logs and configurations. If they are program-wide, and don't need to survive uninstallation of the application, then I think they're fine where they are. If the logs and configurations are user specific, or need to survive uninstallation, then they belong somewhere under %USERPROFILE% - %APPDATA% being the 'proper' base directory for this type of thing.
I use the Isolation Storage for configuration. You can also use the Temp folder to store temporary information like log.

Categories

Resources