I'm writing a service using C# that is supposed to run on a Windows platform as the "local system". I can store small amounts of data in the registry, but if I want to store more data in a file, where do I place such file in? And also how to protect that data from a modification by users with lower access rights?
General approach is to use ProtectedData class to encrypt the data, then store them anywhere on the disk where the application can (eg in a subfolder of LocalApplicationData special folder, whose location you can obtain using Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData call).
Update to previous answer that may save some troubleshooting time to people using this solution (as I don't have enough reputation to comment):
For Local System Windows service account, Environment.SpecialFolder.LocalApplicationData
may also be resolved to
C:\Windows\SysWOW64\config\systemprofile\AppData\Local instead of C:\Windows\System32\Config\SystemProfile\AppData\Local.
Using the already mentioned CommonApplicationData instead of LocalApplicationData does not bring this issue.
Information source: https://www.jamescrowley.net/2014/02/24/appdata-location-when-running-under-system-user-account/
Related
I made an UWP app for Microsoft Store. However, user data automatically saved in the LocalState folder will be deleted every time the app is updated. I want the data to be retained after every updating, so I'm trying to suggest the users to save their data by themselves in the Document folder or somewhere to avoid their data deleted, but I don't want to bother them. Where should I save user data?
The roaming folder will be unable to use in future and I don't want to use Azure because of its fee.
The common approach is to store the data in some remote location, like for example in the cloud. You would typically use a service of some kind to request and save the data.
If you think Azure is to expensive, you'll have to find a cheaper storage solution. The principle is the same regardless of which storage provider you use.
As mentioned in the docs, roaming data is (or at least will be) deprecated. The recommended replacement is Azure App Service.
For the program I'm writing in vs C# wpf I need to store some user related information on the user's computer. As far as I knew this has almost always been done by creating a folder in C:\Program Files and adding whatever program related info to that folder in subfolders or whatever. After doing some browsing I came across a lot of people saying that this method is out of date because sometimes access may be denied to create a folder there, it only works for administrative accounts, etc.. One site suggested saving to c:\users\username\appdata\roaming or c:\users\username\appdata\local. So my question is what is the best and most up to date method for saving program data to users computer?
Also take a look at this MSDN article.
It is mainly for UWP apps but you will have a general idea what to put where even if you are developing a WPF app.
You may need these folders:
Environment.SpecialFolder.ApplicationData
Environment.SpecialFolder.LocalApplicationData
Environment.SpecialFolder.CommonApplicationData
Take a look at this microsoft developer blog Where Should I Store my Data and Configuration Files if I Target Multiple OS Versions:
Here is an example where you can store your Local per user configuration files
Configuration data files that the application uses and is unique per user. It stays local to the individual machine and is not synchronized via Active Directory.
Example: MyMachineSpecificData.xml
Windows 7: %USERPROFILE%\AppData\Local\<MyCompany>\<MyApp>
Vista: %USERPROFILE%\AppData\Local\<MyCompany>\<MyApp>
XP: %USERPROFILE%\Local Settings\Application Data\<MyCompany>\<MyApp>
So basically per user config files should go to:
%USERPROFILE%\AppData\[Roaming,Local]
If those configs should be available to all users then:
%SystemDrive%\ProgramData
For per user data you can use Libraries. For user independent access C:\Users\Public.
Additionally you can also use windows registry to store your configurations.
I am trying to put some files and folders in a place that my WinRT application could access and read files from. These files and folders must be locked and permanent even when I uninstall the application.
There are 4 main categories of folders that you have access to from a Windows Store Application:
/AppData/Local/<yourpackage>
Standard available libraries (Music, Pictures, Videos)
Libraries that require elevated permissions (Documents)
User-defined folders (through a FilePicker)
Typically you will store data specific to your application in the first kind and data for the user in a library or a user-defined folder.
When your application is uninstalled, its package folder under /AppData/Local is removed so there is nothing left there (note that this contains the directories which you get using ApplicationData.Current.Local and ApplicationData.Current.Roaming).
Therefore in order to save data persistent through installations you will have to save them in a different directory. Note however that in the case of option 4, the user might not decide to give you access to the folder he picked out the previous time or that he doesn't want to give the application access to the Documents library.
I think a more solid solution would be to save the data on a remote location so that the user can download it when he installs the application again, rather than relying on everything being saved at the user's device.
With regards to the locking: you could look into the DataProtectionProvider and see if that suits your needs.
To reiterate Jeroen's response:
To save data locally in a place that won't be deleted when the app is uninstalled, you must use the file picker to have the user choose a location.
Saving the data remotely is the only option that doesn't require user interaction.
It's possible to save data in the app's roaming settings, as those are retained for some period of time after the app is uninstalled. If the user has the app installed elsewhere, that data will be retained continuously. If there are no other installations, it will be retained for around a month.
I recently wrote a blog post addressing this exact scenario in more detail, including how to get a persistent user identity for any data your store remotely: http://www.kraigbrockschmidt.com/2014/07/31/persisting-data-after-uninstall/.
I use the following code to build a desired path for an XML file:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
When executed from a Windows Forms application, it returns:
C:\Users\MyUsername\AppData\Roaming\...\Database.xml
When executed from within a Windows Service, it returns:
C:\Windows\system32\config\systemprofile\AppData\Roaming\...\Database.xml
I am now resorting to having a custom installer action persist the path in a registry key since the custom action will have a desktop context. If there is a better approach, please let me know.
What I am really interested in finding out is why the behavior is different in the first place. The Windows Service in question is set up to use the LocalSystem account in case that matters.
Only you know what the specific requirements are for this folder, but if it's to share data between multiple users, ApplicationData is the wrong choice:
The directory that serves as a common repository for application-specific data for the current roaming user.
A roaming user works on more than one computer on a network. A roaming user's profile is kept on a server on the network and is loaded onto a system when the user logs on
See the SpecialFolder enumeration and pick an appropriate value that fits your requirements - one that doesn't depend on a specific user. Most of these start with Common.
I suggest that you should check and make sure that two apps are running by the same user.
I tested your code in both winform app and webservice app, but their values are the same, so I can't find your real problem.
good luck!
I've been working on implementing an api in c#. The implementation is going well, but I did come across a concern.
When my library has authorized against the api I have a auth_token which I use for consequent queries to the webservice.
The token needs to be kept between program runs as it stays the same for the user (although I do check if it is still valid when the application starts).
For testing purposes I basically just save the token into a text file which is kept in the root directory of the app.
This works fine, but is this the best way?
Not sure the user will appreciate that it gets saved in a cleartext file (even if it is on his own pc).
So, what is general practice for saving tokens like this?
I would use the Windows Data Protection There are numerous examples around on how to use it from C#. It uses a user specific key to encrypt the data. Only the user themselves can decrypt it. Also be sure to secure the data during transmission between the server and the client.
Create a settings file for your project in the project properties, add a AuthToken property to the known settings (probably at the user level), then use:
Properties.Settings.Default.AuthToken = userAuthToken;
If you think they'll want it hidden, encrypt or encode the userAuthToken so it is less obvious.
You can verify if the api is used under asp.net or windows environment ( it's enough to check if Request is null) and on the first case use a cookie, on the latter save it on a registry key.
That may work in a local app or running the CI locally, but if you are in DevOps (Azure) your test app will reside in your VM bin folder. After every deployment your bin folder gets wiped out so the token you saved in your bin files is gone. Perhaps the best way to save it will be encrypted in one of your DevOps environment variables in your release pipeline so you don't loose it. When running locally you can save it anywhere.