Sharing files, and how to stay updated? - c#

I have a program I use on multiple computers, that I would like to keep in sync to each other.
The files shared are .json and .txt files. Am I just able to serialize back to the file every so often without cause for concern? The software is used to make transactions on an inventory, it is only used on 1 computer, and then I use the software to make purchases or restock the items after purchased. I just want to be able to access it from my computer without having to walk to the other computer, close it, and open it on my computer make my changes and close it, walk back and open it back up.
I haven't dug into this at all, as I'm not sure what exactly it is called that I am looking for.
I would think if I can just serialize back to the file it would be ok, but maybe there is an easy way to check if the file has been saved over since I have had it open on my computer?

If you want to check whether or not the file was altered since some defined point in time look at the FileInfo. If you have several computers running put the file on a shared folder and use a FileSystemWatcher. In general I think there is nothing principally not working with serializing/deserializing data to disc.
Nevertheless I would suggest backing up data and considering concurrency.

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.

Permanently add a database to an application C#

I'm trying to create software that will add a computer to an Active Directory domain. One criteria I need to meet is the machine must be added to the proper OU. In order to do this I have a set list of site locations with addresses (this is how we determine OU). This list is currently in the form of an ACCDB file, and I want to include this within the application as the Access list will not be changed.
Everything I see wants the DB file to be connected to in a different location such as server or on the local machine. My preference is to use the DB file as a reference or something inside the program's .exe file itself. I may be missing something horribly obvious, but it's been messing with me for a couple days so I'm reaching out for help.
To clarify, this software MUST be self contained (no installer). It must also be able to determine the proper OU to join to the domain (no access to shares until the PC joins the domain). It must also be user-friendly enough to avoid mistakes, meaning I want to avoid copying distributing multiple files that must go to a correct location. This is why I want to embed the ACCDB file into the application for on the fly use.
Things get much easier because this is static data. You don't have to worry about persisting this data, reclaiming changes into your program, or users accidentally deleting something, etc. You will be able to just use an embedded resource in your application. In the link, follow the examples using the image file. Text file examples will corrupt your database.
However, there is still a trick to doing this. The problem is the Access engine included with Windows will not be able to open the database as a resource, and so you will need to save this file to the local hard drive. The good news is its not as bad as it seems, because your program can do this as needed, and make sure it's right, rather than asking the user to put a file in a specific place.
As for where to put the file when you extract it... the safest and best place is the Application Data folder. You can easily get the path for this folder by checking the results of this call:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
This will give you a path where standard privilege users do have write access, no matter which user.
In summary:
Embed the ACCDB as a resource.
When your program runs, get the Application Data path using the Environment object.
Open a FileStream for writing to a file based on the path from #2
Open the embedded resource as a Stream object in C#
Copy the stream from #4 to the stream from #3. Make sure to use a mechanism intended for binary data, rather than text.
Close/Dispose your streams, so no locks remain on the file. This is as simple as putting using blocks in the right places.
Open a normal Access connection to the file you just made, using any of the thousands of tutorials or examples available on the web as a guide.
In this way, you only need to distribute the final .exe file, and users won't need any special permissions to use the database. You don't have to worry if a user deletes your file; it's still embedded in the application, which will recreate it if needed every time it starts up.
The downside is a clever user may be able to manipulate the database to end up in an undesirable OU. If you need to worry about this, you should consider having the program check a web service, rather than using embedded data. Anything you embed can ultimately be altered by an end user. A web service is also nice because you can update your mapping data as your organization evolves, without needing to rebuild or redistribute the program.

storing ntfs file metadata for retrieval via webserver and linking with database

I am looking for a few pointers to reaching am adequate solution to a problem/feature I need to implement/rectify in my asp.net mvc application.
My application is a LAN only interface that is run over a webserver. In this application there is a page that displays a bunch of files/folders.
I need to be able to store a set of attributes\properties about these files, and those props\attrs need to be independent of their location on the fileserver. This is my main issue, as I could easily link them to the db with the path as the primary key, but alas then as soon as the file moves their link to the db would be lost.
The types of files that need to be displayed unfortunately could be anything. .txt, .exe, media etc etc. So that provides a limiting option also from using something like the tagsharp lib.
One approach i was considering was simply storing a key somehow in the file itself, or with an ADS ( i have no experience in doing this, but am presently trying to research its potentiality).
Does anybody have any experience with this issue, and can recommend a simple approach. I am hoping i do not need to implement an ADS approach as what ive been reading so far is a little bit over my head and im not sure C# will handle the streams adequately for my needs.
Opinion based. Proposal anyway: what about an additional file which is found by a naming convention?
MyDocument.doxc
MyDomument.docx.properties
MyMovie.mp4
MyMovie.mp4.properties
When moving / renaming files, make sure you move / rename the properties file the same.
First of all thanks for taking a moment to reply.
I had considered the possibility of using a separate file. The problem is that the users of the filesystem ( which may or may not include users of the lan application ) need to be able to move/copy files independent of db application.
Therefore if a user moves a file in windows explorer, I need it to automatically move those additional properties with it. Unfortunately I cant rely on users to move those additional files on their own volition, and I cant ask users to only use the application to move files ( if i were to generate code for the program to do this ).

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?

Responding to interactions with files in C#?

I want to write a program that will encrypt an entire folder and it's sub-folders, I have no problem doing this but I would like to make the entire encryption process rather transparent by letting a user double click it and have it open as if it weren't encrypted, say if it were a picture or a word document and it'd open in it's respective application.
How can a running program of mine become notified about the opening of a target file, stop the file from opening, do what it needs to do (decrypt), followed by running the resulting decrypted file.
How can I watch a file and do this in C#? Can I watch for other interactions like the user copying a watched file (since it won't be in a watched folder, it should be decrypted i.e. it's dragged to a USB device), or for deleting a watched file (say if I want to shred a file before deletion)?
P.S. The FileSystemWatcher doesn't quite meet my needs. EDIT: What I mean is that FileSystemWatcher will tell me when a file is being opened, deleted and all those events, but it won't let me step in real quick, decrypt the file, and hand it back to the process that normally opens that file.
You can rename files, add them your own extension, like thepicture.jpg.encrypted. Set your program as a default program for this extension and handle opening them
It's impossible in C#. the bare minimum would need you to use user-mode hooks on NtCreateFile, NtOpenFile, etc. You can't achieve that in C#. That wouldn't even work properly due to kernel-mode code which may try to access your files. The proper way of doing this would be to write a I/O minifilter (in C of course).
EDIT: If you're really desperate, try EasyHook - it allows you to hook functions from C#. I haven't tried it though, and it does seem risky hooking vital functions like NtCreateFile. Plus you need a fair bit of Native API knowledge.
Are you using Windows? If so, why not use the built-in BitLocker?
See this link:
BitLocker drive encryption
If you are thinking about a competitive application to BitLocker, add a comment, as I can point you in that direction as well.
Instead of trying to reinvent the wheel, use NTFS file encryption. You can encrypt single files or entire folders or drives. Plus it's completely transparent to the user and does exactly what you asks (e.g. automatically decrypt when copying to a UBS drive, etc). Just use System.IO.File.Encrypt(string) - there couldn't be anything easier.
You can't do this from usermode.
Unfortunately the only way to do this is to write a minifilter driver. Minifilter drivers allow you to intercept IO requests to files, you can then encrypt/decrypt the files you care about on the fly.
It sounds simple, but encryption minifilter drivers are very, very, difficult to get right. You will have to end up shadowing file objects which is a real challenge. Check with www.osr.com, they have a ton of information on doing exactly what you want to do.
If you choose to go this route I would recommend getting a copy of VMWare Workstation and download VirtualKD. It will let you debug at near fire-wire speeds into a VM. I would start with x64 Win7 and get remote shares working first.

Categories