I have an ini file in my application but where should i save the file and why should i do that?
If i use Environment.CurrentDirectory where is the file saved if i publish my application?
I also have an additional question, i hope that's okay.
I don't want to create an additional question for that.
If i publish my application how can i create an setup for my application, like the default one, not just this install application windows where you can click install now or not. And where the user could change things like where the application is installed and so on.
Where should a ini-File then the be saved or where would it make sense?
If anybody has a useful link or a good tutorial for this it would be nice.
Thanks in Advance
ApplicationData is probably your best bet:
The directory that serves as a common repository for application-specific data for the current roaming user.
There's also
LocalApplicationData: Current user, non-roaming
CommonApplicationData: All users (not specific to any one user)
Here's how you can get the correct location for storing your file:
Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData), "yourFile.ini");
As for your second question, I'm not sure what a good setup program would be. It really is a separate question, but as it's asking about a recommendation for a tool, it may be closed.
Related
My application basically creates an XML file in C:\ProgramData\MyAppFolder and dumps config settings in it.
I need to allow even standard users to have permission to add or delete settings to these config files. Right now I see that standard users only have read/execute permission but not "Full Control".
I've seen other questions being answered with ways to modify permissions to that particular folder but I don't want to change the default permission level, since it might be reset by a system admin.
If C:\ProgramData can't give that access to all users, is there any folder that best suits the needs of application?
EDIT:
My initial question might be misleading. I don't want to give rights to users, but rather allow the application to modify the XML file when it is run by all users.
DECISION:
I think changing the permissions while creating the folder in ProgramData is the only option.
And if that's not possible, CommonDocuments is the way to go.
Thanks Eve.
I would use a folder in the Environment.SpecialFolder enum.
Example:
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
Assuming you have an installer for your application, your installer can create a subfolder in the common appdata directory (aka C:\ProgramData) which your application will have read/write access to. Depending on your choice of installation technology you can set the permissions on that folder as well, although that may be overkill. I know with WiX basically all you have to do is a per-machine installation and make sure that sub folder gets created.
Users should not be allowed to write arbitrary data to this directory. This is equivalent to regular users being able to modify the C:\Users\AllUsers directory. If users need to be modifying this directory you have serious design flaws and should reconsider this approach. What should happen is the users are given GUI interface to interact with that manipulates these values behind the scenes without giving them direct access, similar to how getters/setters work in most programming languages. Needless to say it is a very large security hole when regular users can corrupt a system for other users.
UPDATE
I don't want to give users direct access to the file. My question
might have been misleading. I want to allow the program to have full
control on the file even when it being run by all users. I'm actually
doing this: "users are given GUI interface to interact with that
manipulates these values behind the scenes without giving them direct
access"
This article which has far too much information to post here, will provide details on remaining secure as to not leak permissions. The first thing you want to do is make sure that your application user is in its own group and cannot login/have any special permissions. What you can than do is have this group added to the directory with write permissions, which would allow this application to perform these tasks. If that is not possible you will need to work within UAC to not break the security of the system as is detailed in the article above.
Second Update
Thanks for the link. Any suggestions on some other folder which can do
the job, rather than messing with the permissions?
Sure you can write it into the directory where the application is written to, i.e. C:\Program Files\Some Awesome Program, this keeps everything in one place, and you only have to worry about your user/group and anything that the person who installed it has allowed for. It also prevents other people from messing with it unless of course they are administrators.
We have a C#.Net application which uses a network database. I mean to say that many instances of the application will access the same db from different machines. So if I have to store the user-id to show the user while re-logging in, where can I store it?
The options i have are:
- Storing it in a local file in application directory. (But the problem is that the application is installed using Click Once. When the application is updated the application directory is being changed. May be I am missing something here.)
- Storing in the registry. Are there any other?
Can some one please suggest what to do? Correct me if I am wrong.
There are buil-int locations for this kind of stuff see Environment - specifically:
ApplicationData (user-specific roaming)
LocalApplicationData (user-specific non-roaming)
CommonApplicationData (not user-specific)
Generally you want to store any data that needs to persist between sessions, and is user specific in the registry, or the user AppData folder. Normally for small things (i.e. ids, basic settings etc....) the registry is the best place. Just make sure to stick it under HKCU\Software\Your company name\your program name. Although if the data is sensitive you should be careful where you place it, and it should be encryptedto protect it from basic snooping. If it's data that isn't sensitive though then the registry is a good place to put it.
This assumes of course that the installation and configuration doesn't need to be xcopy portable (i.e. a user could just copy the installation folder to a new place/computer and have everything work as normal). If that's the case then you'll want to store it under the installation directory.
If you need to store the UserID on the local, keep it in some kind of configuration file, mabe under a "LastLogin" entry. Check out this question and specifically this answer for more information.
Consider using Isolated Storage
I'm not sure if the question's title makes sense, and I'm sorry if it doesn't; I didn't really know what to title it.. Anyway, is there a way to make your program track the viewing of a folder?
What I'm trying to achieve: Windows 7 Home Premium doesn't allow encryption. So, I made a folder inside my user directory, and set it to hidden. Although, you can easily find it by changing windows settings.. So, is there a way to make a program pull up a window if the user tries to access that certain folder?
I don't think you can detect the "opening" of a folder.
Instead, you may want to set a FileSystemWatcher to detect any file access to the files in that particular folder.
Hope this helps.
First of all, I have to wonder why you're not just setting an ACL on the directory to prevent access.
However, it sounds like you want to find when somebody is accessing a particular directory. To do this, you enable filesystem auditing, then set the audit ACL to generate audit entries for "List folder". This will cause entries to be generated in the Security Event Log whenever the directory is viewed.
Now you just have to write a program that watches the Security event log looking for entries indicating that somebody has listed the directory in question and take action as necessary.
Well, there is an article on code project describing how you can hook into windows system calls: http://www.codeproject.com/KB/system/hooksys.aspx - it's not simple though (and also not C#) and has the potential to screw with your system but if it might be a fun project to work on.
A simpler option would be: Use a 3rd party desktop encryption tool - not much programming involved here but it might do the job better than anything else.
I'm programming a fairly simple application which I want to cut to just one simple EXE file + some data storage (XML for example).
My question is regarding configuration files. Where to put those files? I saw a few applications that have just an EXE file (uTorrent, Media Player Classic - I can use them without any installation), but they store their config somewhere else. How to achieve this?
How would you approach such situation? Is it better to try to achieve the thing I described above, or simply use a configuration file and data storage in the same directory as the EXE file?
Creating or using a file in the same folder (or in the App_Data) is pretty standard practice.
You use an installer like Inno Setup (free) to create a single exe installer (http://www.jrsoftware.org/isinfo.php)
If you want a DB rather than XML, have a look at SQLite (http://www.sqlite.org/) a file based DB or use an MS Access DB.
I think you want to take a look at Application Settings. This is an API which allows you to save user or application settings using a strongly typed API. Under the hood the settings are stored via XML serialization.
This API works with virtually every type of .Net application including low permission Click Once versions. It does the work of finding the place on disk appropriate for storing the data and completely hides it from you. It also has a nice GUI integration into Visual Studio.
EXE-only programs store their data either in the Windows Registry or in the user's Application Data/AppData folder. Although this may appear cleaner at first, it just hides the ugliness of scattering all your data around. I would suggest just going with a simple XML/INI/text data file that is generated when needed and easy to migrate.
Please see: WPF/C#: Where should I be saving user preferences files?
You could use the app.config file for storing your configuration. For the data, I would sugest something like db4o or SQLite.
Edit
This tutorial can show you how simple is to use db40 to store and retrieve your data.
Do not forget Isolated Storage. It gives you a place to read and write files to without the need for you to specify a location. Sometimes it is the only way sandboxed applications (like Silverlight) can store user or machine specific data locally. See here for an example.
I would store them in the same directory. That just seems easier to me, at least that's the way I always do it.
What is the recommended location to save user preference files? Is there a recommended method for dealing with user preferences?
Currently I use the path returned from typeof(MyLibrary).Assembly.Location as a default location to store files generated or required by the application.
EDIT:
I found two related/interesting questions:
Best place to save user information for Windows XP and Vista applications
What's the way to implement Save / Load functionality?
EDIT #2:
This is just a note for people like me who had never used settings before.
Settings are pretty useful, but I had to do a whole bunch of digging to figure out what was going on (coming from the Python world, not something I am used too). Things got complicated as I wanted to save dictionaries and apparently they can't be serialized. Settings also seem to get stored in 3 different files depending on what you do. There is an app.config, user.config and a settings.setting file. So here are two more links that I found useful:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/ddeaca86-a093-4997-82c9-01bc0c630138
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/efe370dc-f933-4e55-adf7-3cd8063949b0/
You can use the Application Settings easily enough.
If you haven't done so before just right click on the project and choose Properties. Select the Settings tab. Make sure you chose "User" for the scope (otherwise the setting is read-only).
The code to access this is simple:
forms.Width = Application1.Properties.Settings.Default.Width;
If you need to save it:
Application1.Properties.Settings.Default.Width = forms.Width;
Application1.Properties.Settings.Default.Save();
In the sample above, Width is the custom setting name you define in the Settings tab and Application1 is the Namespace of your application.
Edit: Responding to further questions
You mentioned you wanted to store Dictionary objects in the Settings. As you discovered, you can't do this directly because Dictionary objects are not serializable. However, you can create your own serializable dictionary pretty easily. Paul Welzer had an excellent example on his blog.
You have a couple of links which sort of muddy the situation a little. Your original question is where to save "User Preference Files". I'm pretty certain Microsoft's intention with the Settings functionality is exactly that... storing user skin preferences, layout choices, etc. It not meant as a generic repository for an application's data although it could be easily abused that way.
The data is stored in separate places for a good reason. Some of the settings are Application settings and are read-only. These are settings which the app needs to function but is not specific to a user (for example, URIs to app resources or maybe a tax rate). These are stored in the app.config.
User settings are stored in an obfuscated directory deep within the User Document/Settings folder. The defaults are stored in app.config (I think, can't recall for certain off the top of my head) but any user changes are stored in their personal folder. This is meant for data that changes from user to user. (By "user" I mean Windows user, not your app's user.)
Hope this clarified this somewhat for you. The system is actually pretty simple. It might seem a little foreign at first but after a few days of using it you'll never have to think of it again... it just works.
When running as non-admin or on Vista you can't write to the "Program files" folder (or any sub folder of it).
The correct location to store user preference is (replace MyCompanyName and MyApplicationName with the correct names, obviously)
On disk:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\MyCompanyName\\MyApplicationName"
Or in the registry under the key:
HKEY_CURRENT_USER\Software\MyCompanyName\MyApplicationName
Those location are per-user and they work with non-admin user, several users using the same computer, fast user switching, terminal services and all the other ways people can interact with your software.
If you need a common location for all users then:
It will only work when the user run as an administrator
It will not work reliably on Vista
You have to take care of everything yourself (like two users running the application on the same computer at the same time via fast user switching).
and the locations are:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationCommonData) + "\\MyCompanyName\\MyApplicationName"
Or in the registry under the key:
HKEY_LOCAL_MACHINE\Software\MyCompanyName\MyApplicationName
You can use isolated storage. You can isolate by user, assembly and/or domain.
Introduction to Isolated Storage
http://msdn.microsoft.com/en-us/library/3ak841sy(VS.80).aspx
Types of Isolation
http://msdn.microsoft.com/en-us/library/eh5d60e1(VS.80).aspx
the following seems to be the best option:
Application.UserAppDataPath