Search code examples
c#ms-accessembedded-resource

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.


Solution

  • 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:

    1. Embed the ACCDB as a resource.
    2. When your program runs, get the Application Data path using the Environment object.
    3. Open a FileStream for writing to a file based on the path from #2
    4. Open the embedded resource as a Stream object in C#
    5. Copy the stream from #4 to the stream from #3. Make sure to use a mechanism intended for binary data, rather than text.
    6. Close/Dispose your streams, so no locks remain on the file. This is as simple as putting using blocks in the right places.
    7. 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.