Where should I save database files? - c#

So far in development, my application has been storing its databases in the app base directory. When it is deployed this will be in program files so I cant keep them there!
The obvoius places are:
Environment.SpecialFolder.LocalApplicationData
Environment.SpecialFolder.ApplicationData
One problem is that data downloads can be run from sceduled tasks so I would have to ensure tasks were run under the same user.
The major issue is that after a couple of years, these database files could total 5 to 10GB, so I feel like I should give the user an option after install to choose the database location. I'd have to ensure that it was writable and not a network location.
What solutions have others come up with?

About checking the write access to a directory: So far I have found no better way than to create a file in the directory and immediately delete it. If you encounter an error during these steps, you have insufficient privilegs. (Just remember to first check if there is enough free space on the drive).
I once tried to solve this programmatically by going through the access control lists, but then i encountered a dir where I had write priviliges, but not the right to list the ACLs...
You can check if a given drive is a network share by using the DriveType property of the System.IO.DriveInfo object. As for handling UNC pathes, I have yet to find a better way than (myPath.Substring(0,2) == #"\\")

Related

How to hide (zip)files from users or make them mutable

We are trying to make sure that our users can't under any circumstances alter the files in any way.
Is there a way to prevent normal non-admin users from interacting with files that my application need to interact with?
Say there are N amount of files that my application interact with. Once the application get a reference for these files then users should not be able to interact with them. Right now I am making a copy of the files and hide them under appdata in my applications folder.
This works for the normal Joe, who is just doing his job and working hard as he will never try to look for trouble down there, but the bored Adam will probably go and play hacker when nothing special happens.
The files are storred on the local computer until they are sent, with another application, to a remote database. The time between the files first interaction with my application and the event of being transferred to the database can range from seconds to weeks.
I have a local database on the computer, but I can not store the files there because there can be N amount files that needs to be transferred and some other data needs to be stored in the database as well. I believe the max capacity of the database is 4 GB, which would make it impossible to store the data.
The computer is also not under my supervision, so I am not allowed to change OS settings, and I can't store the data remotely either, because if I could then it would be sent to the remote server.
My current solution hack solution would be to hold the file in memory (so it can't be changed durring the process) create a hash of it, which I will store in the database, and then make X amount of copies that I will spread out in different parts of the computer. This way Adam needs to touch more than one file, which are all in a non-disclossed location, to be able to sabotage everything. This would also require him to search in a couple of folders to find the files, which would require work and which Adam will probably try to avoid.
The problem here is that I don't really know what kind of sociopathic maniac Adam is, so even by going this far would still be throwing die with god.
That's why I am wondering if there are places where Adam can't touch or ways to hide/lock the files in a way so that Adam can't alter och destroy them?
Is there a way to prevent normal non-admin users from interacting with files that my application need to interact with?
Programs run in the context of the user that starts them. If your user is not able to edit a file, your program won't be able to edit it, either. If your program is able to edit the file, your users WILL ultimately have that ability. There is no separating the two.
As an example, zip files also support password protection. So you could put everything in a password-protected zip file, where the password is embedded/obfuscated in your application and not known to the user. In this case, it will be extremely difficult for the user to open the zip file in the normal way. But even then, the user will still able to tamper with the file via a text editor. They may not come out with anything useful, but they did still modify the file.
The one thing you can do is detect the tampering. You can compute and save a hash value for your files, and check the contents of the file match the saved hash.
One other thing option you may have is using multiple databases. I don't know what kind of database you have that's giving you a 4 GB limit, but if it's something file-based like sqlite there's no reason not to have multiple files. Keep in mind, though, the user still has the ability to tamper with these files in a text editor. If it's SQL Server Express, the version with the 4 GB limit has been end-of-life and fully-unsupported for several years and should not be used! Newer releases of Express are still free and now offer a 10 GB limit, and also allow you to have multiple databases with a 10 GB limit each.

.NET Directory.Move results in Access to path is denied with network paths

I know there are a bunch of these questions already but none of the ones I found depict the scenario I have.
So what I want to do is to
move a directory via Directory.Move. Both source and destination are on a file server in the same network so both paths are network paths (starting with \\SERVER rather than a drive letter).
The application that‘s supposed to do that gives me an „UnauthorizedException: Access is denied“. Because it‘s confidential I can‘t show the log or code.
But I tried to reproduce it by simply calling Directory.Move via PowerShell ([System.IO.Directory]::Move()). There I receive the same message. Access to path X is denied. Nothing more.
This error appears with any user context. An admin, an admin with „run as admin“, the user of the application and the user of the application with „run as admin“.
Manually moving these directories works without a problem.
Creating a directory with Directory.CreateDirectory works too. But moving the newly created Directory results in the same error.
Executing these commands on the file server works just fine if using the local path. Using the network path (still on the actual fileserver, though) results again in the Acces is denied error.
Could it be, that the issue lies within the path rather than the directory? The permissions are all correct and set (as said, manual operations work). Are there any workarounds?
I really don‘t know what to do. I‘m the only developer at this company and the rest are network engineers and can‘t help
me either.
There are a number of things that could be causing it to deny access and it would be hard to point you in the right direction without seeing your code. But here are 2 scenarios that might help you.
Scenario 1 - The filepath you are using is in the wrong format, Usually I have had a access denied because the format of the network filepath was actually wrong. I would recommend looking up examples of how you should pass the filepath. Also have a talk with your network engineers and ask them about the rights that have been setup for that filepath.
Scenario 2 - You might be passing a filepath when you also need to specify a name. Now I dont have all the details but I also had issues in the past using the Directory.Move function where I actually had to specify a filename to move it to. You do this by just adding the file and extension to the end of the target path to copy to.
If you could post some more information I might be able to point you in the right direction but this is what I can think of for now. I hope this works for you or atleast brings you closer to an answer. Good luck!
*Edit: It looks like I am wrong on the scenarios, Have a look at this link Can you move a file/folder across a network share in .NET?
You will have to first manually create the filepath and then copy all the files into the new filepath you have created. It seems like Directory.Move has problems when different machines are used.

Where to put common user program data in Windows XP/Vista/7/8/10?

It may seem like this question has been asked a thousand times before, but I can't find an answer that actually points to a path that is common AND writable for all users.
In any case - in my application the users can download some fairly large data files that need to be accessible to the application after download. The application is used in multi user enviroments, so I'm not interested in storing a copy of the downloaded files for each user.
So far I've been using CommonApplicationData (C:\ProgramData\[Vendor]\[Application] created using Wix installer), but I've recently learned that this is meant as readonly storage and several users have experienced issues with this because CommonApplicationData is write protected.
I've been checking different options and the only viable one I have found so far is the %public% folder (https://blogs.msdn.microsoft.com/cjacks/2008/02/05/where-should-i-write-program-data-instead-of-program-files/).
Is this the best/correct place to put the files or is there another solution? Needs to work in Windows XP/Vista/7/8/10.
CommonApplicationData is indeed the correct place to store this data, unless the users should be able to see them as documents to double-click.
When you create the folder (or the individual files or subfolders within it) you should set the permissions according to your needs.
One alternative approach, to provide better cross-user security, is to install a system service to download and install these files on the users behalf.

C# - Locking folders from being edited

i'm making a small project. it's Windows Form Application. i got some sources in a folder (C:/sources). When my program runs, it uses sources from the folder. Currently i can edit the folder by windows explorer, it can cause errors for my program. So i want to lock the folder (C:/sources) from being edited/renamed/deleted when my program runs. How to do so?
EDIT;
Is it possible to show a message like this when user has tried to edit the folder:
"the action cannot be completed because the folder or a file in it is open in another program"
the program that we are talking about is mine..
There are a couple of approaches that you could venture and they vary in difficulty of implementation. It all depends on how important this task is for you. But, before discussing these options; can't you embed those resources in your WinForms application instead? If this is not an option then you can do one of the following:
Write a device driver that can prohibit the access of such resources if your application is running. There are fallbacks to this approach. For example one can impersonate your application by having the same name. But, am not getting in to too much details in trying to break any approach as I am trying to address possible solutions to the current problem. There are different types of drivers that you can consider. Probably the simplest form of this approach would be to implement a mini-filter driver.
Hook certain API's like CreateFile(), NtCreateFile(), ZwCreateFile() although there are many ways to circumvent such mechanism of defense. But, again we are only venturing what you can do to address this constraint of yours.
Open these resources directly from your application and lock it exclusively. For example:
File.Open("test.txt", FileMode.Open, FileAccess.Read, FileShare.None);
as this will result in people getting the message that you desire if they try to open the file.
Maybe you can give more information on what these resources are and we can help you determine which is the best way to protect your files in a reasonable fashion?
Although I don't believe it's the best idea to have files that are critical to the application in a open area like the C: drive, I would look into NTFS file permissions and set the folder to read only, but this wont stop administrative users
See these two posts
restrict access to folder outside of program c#
Setting NTFS permissions in C#.NET

General file attribute to identify file without its path or even name

I am working on an application that keeps track and uses files stored on the file system. Users are allowed to open, create, delete and move files in the file system. Meanwhile my application is not constantly running so I can't keep track of all changes real-time. Afterwards my application has to find out what file is whom (i.c. as identified in my application).
The most preferred solution for the users is that the application solves every change itself. Each user-interaction is less preferred.
One of my ideas was to use an attribute of a file and assign a key-value to it so when it has been identified once, it can always been recognized afterwards. But I don't know if there is such an attribute. This article didn't give much hope: There is in Windows file systems a pre computed hash for each file?.
Does somebody know if there is such an attribute I can use? And how can I used it in C#?
Is there anyone who is running up against this problem? And how did you solve it?
I'd like to hear good suggestions.
regards, Jaap
If your files don't leave NTFS, this is easily achievable by alternative data streams, where you can store your data along with files. This is more-or-less good article about ADS: http://www.flexhex.com/docs/articles/alternate-streams.phtml
There is another suitable method - it's very efficient, but also very complicated to use, it requires quite good knowledge about NTFS internals - USN Change Journal; see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363798.aspx. With USN Change Journal, you can "get" very efficiently all files that were changed (even all change events) within specified time period.
Nevertheless, if your files leave NTFS realm, e.g. if it's copied to FAT32, contents of ADS is lost.
Relying on a File attribute is "dangerous" in that some user could alter the attribute while your program isn't running. This could lead you to believe that a certain file is (or isn't) tracked by the program while it really isn't.
I would suggest to keep track of the files in a database, XML, or some other file. When your application starts you read the file/db and check for new/deleted/editted files.
You could store a Hash of the files to find out if a file has been moved/editted. Keeping track of files that are moved AND editted is going to be pretty difficult. (I have no clue how you could achieve it)
PS: Have you considered making your application a Windows service? Having the file-management running in the background no matter if the GUI part of your application is running or not?

Categories