Distributing an Access database with a Winforms app - c#

I have a C# app which reads from and writes to an Access database. There is one database file per user. My intention is to check for the existence of the MDB in the user's My Documents folder at launch, and if the MDB isn't found, then copy the template MDB to that folder.
I have already added the template MDB to my project and placed it in its own folder which I have called Packaged. However, I am unable to refer to this Packaged folder from code as it doesn't appear in IntelliSense.
My intention had been to use File.Copy to copy the MDB over, but I cannot determine the file path as I can't access the MDB in code. And presumably it wouldn't have a file path anyway if it's just packaged in the .exe?
What would be the best way to achieve this, given that I would rather not distribute a separate MDB if possible?

I've done this in the past by making the MDB an embedded resource, and writing it to disk as needed (if it doesn't exist).
Here is more info on writing an embedded resource to file.

You'd almost have to use one of the Environmental paths for the template MDB. Like ApplicationData or Documents and Settings\Username\Local Settings\ or one of the other ones. Local User Data is the best way for user specific data. IN the code in the beginning, determine to see if the file exists in the first run. If it exists copy the template, if not don't.
That way the user has full read and write access and the ability to copy the file or duplicate the file without security problems. These environmental variables are accessible through
Environment.GetEnvironmentVariable
You could also have a registry setting and read and write to the registry for that specific application, that has a simple DatabaseAvailable key, and toggle it yes or no.
You could also embed the MDB as a resource too, and then write it as necessary.

Related

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.

How to limit folder/file access to a program only?

Okay, so I am creating a c# winforms application.
I want to write/read from binary data file. But, I want to put that file in a folder somewhere and I do not want anyone to be able to delete or edit the file. I only want the program that uses the file to be able to access it.
Is this possible? I looked into MSDN's structure on file security and as I researched it I saw people complain that if you limit the file to a user then that person can just override the privileges and make it editable.
Also, I thought about how this would actually work considering in essence I would like a process to edit the file only and that process could have varying process ID's if it is opened and closed over time, seems tough.
Any thoughts?
Even though this will not satisfy all your requirements you can try IsolatedStorage (System.IO.IsolatedStorage Namespace).
How to write and read file in IsolatedStorage
The System.IO.IsolatedStorage namespace contains types that allow the
creation and use of isolated stores. With these stores, you can read
and write data that less trusted code cannot access and prevent the
exposure of sensitive information that can be saved elsewhere on the
file system. Data is stored in compartments that are isolated by the
current user and by the assembly in which the code exists.
Additionally, data can be isolated by domain. Roaming profiles can be
used in conjunction with isolated storage so isolated stores will
travel with the user's profile. The IsolatedStorageScope enumeration
indicates different types of isolation. For more information about
when to use isolated storage
You can prevent file access while your program is running if you open it exclusively.
However, when the program is not running, the file is no longer protected. So someone would just need to kill the program in order to access the file.
In order to protect the file while your program is not running, you'd need to set up a user account and assign it a password which is only known to the program. Then set the permissions of the file so that only your user can access the file.
However, any administrator can take over the ownership of the file, so even permission protection is useless.
Finally, someone can even take the hard disk out of the PC and read the raw data.
You might also think about whether you want to protect the file or the file content. If the file content is sensitive, think about encryption.
It really depends on your needs, which option to choose.
If you have control over the target filesystem prior to install then setup some file permissions and go from there. The user accessing the folder will need read permissions at minimum.
Run the app under a security group and assign persmissions to the folder and files with that security group. Revoke access for others and make it readonly
Windows 10 version 1709 introduced Controlled Folder Access. This allows you to whitelist applications that can modify certain folders. You cannot restrict Read access.
well, I have the same issue and I did some research on this subject and I found that secure your information in a accesspoint database or any other Microsoft data base with password and only one specific app that have the password will have the permission to do read/write to these information.

.net WPF application create a secure folder

I am working on one desktop application which is built by using .net WPF. I have some data inside the application like images,videos..
I want to make this folder secure, so nobody can access the data inside the folder after application installation. Only the application can read the data from that directory.
Even though administrator of that machine can not open that folder to check the content.
Is it possible to have this kind of security inside the WPF application.
Only motive it to keep the sensitive data protected from external copy from the application users.
Thanks,
Vijay
It depends on how you use the resources.
Actually you could encrypt all "protected" files, so that after the installation every one can copy but no one can use them unless your application decrypts the files.
When you encrypt files you should definitively test the performance (decryption takes some time).
Two links showing how you could do it:
What's the easiest way to encrypt a file in c#?
http://lukhezo.com/2011/11/06/encrypting-files-in-net-using-the-advanced-encryption-standard-aes/
Add the file you would like to strongly protect to you solution. Then right click each file, go to properties and set its "build action" to "embedded resource".
And for how to access the resource stream from within the exe for use with in your application, see link below
How to compile all files to one exe?
That way, your private files will not be copied to the installation folder but will instead reside inside your .exe file.
WPF is beside the point. Applications run with the permissions of the users that start them. If an application needs access to files, then the user will also need rights to those files.
In short, the answer is no, you cannot do exactly what you are asking.
The best you will be able to do is make it hard for a user to discover where the assets are coming from, but you will never be able to give access to your application without giving access to the application's user.

ClickOnce Application user settings locations

I am currently developing a ClickOnce application that converts CSV files for a database update. The program requires the user to have the ability to change the configuration files for a database change, and change an XML file which populates a drop-down list in the app.
Now I understand that the files are kept in the user/appdata folder to ensure there have the correct privileges, but do I have any influence as to what those folders are called, or where they are saved?
By default, the files are saved in AppData\Local\Apps\2.0\LD7ZEJK0.7AE\NJ42PEPW.1QX\csvt...exe_169e1a4011fbe7ec_0001.0000_none_04507fe9e077ae84
Can I change that to say Documents\CSV_Files or something similar? And if I do, how would I reference the XML file in the configuration file so the program knows where it is?
Normally, you shouldn't have to care about the location yourself. Just mark your XML file as data in the ClickOnce manifest and access it using the well-known:
ApplicationDeployment.CurrentDeployment.DataDirectory
Here's an MSDN article describing it: Accessing Local and Remote Data in ClickOnce Applications
I would never store any data that is important to be retained in the case of an update in the actual ClickOnce deployment directories -- it is too dangerous. You should copy those files out to ApplicationData and access them there. This article shows you how to do that.

Copying the database through the code

I have a database that I connect as a file, i.e. through the AttachDBFile attribute in ConnectionString in web.config file of ASP.NET site. The database is in the App_Data folder od the website. I made a small app, that should allow to copy paste (a kind of backup functionality) the database to any chosen directory. For this I am using FileDialog box for allowing the user to chose the destination directory. I am using the .NET FileSystem API for copy pasting. The problem is that, I cannot copy paste the database till I shut down the SQL Express service. During copy, a dialog saying that the file is currently under use by other process is shown. If I turn off the service I can copy paste the database.
I used AttachDBFile attribute, since I thought that it will allow such copy, since this doesnt directly attach the database to the server. But now I think its not like that. :(
So how I can deal with this. Please help. Thank you.
You get the error since the file is locked while it's in use.
Have a look at the recommended ways to backup your database at msdn: http://msdn.microsoft.com/en-us/library/ms187510.aspx.

Categories