Issue Related to Read only DB file after installation - c#

I have an Application in WinForms,
I have created SetupDevelopment project and then install an application using Setup.exe file
i have added MSAcceess db file into application folder file,
when i install an application the database file gets readonly. how can i make file writtable after installation?
I found some solution on internet and found that when i tried to install application in different path other than "C:\ProgramFile\" and make application available to all user,it solves my Problem, but i want to install an application only in "C:\ProgramFile\" and want to available to only "Current user"
how can i achieve my Problem ?

In modern Windows Operating System the folders 'Program Files' or 'Program Files (x86)' are read only for the common users. This choice has been done for security reasons and you cannot easily bypass this rule. The reccomended folders, to use just for the current user, are C:\users\username\AppData\Roaming or C:\users\username\AppData\Local identified by the Environment.SpecialFolder.ApplicationData or Environment.SpecialFolder.LocalApplicationData. To this base folders add another subfolder identifying your application or company and install your database there.
If you want your database available to all users of the current PC, you could install it in the Environment.SpecialFolder.CommonApplicationData that resolves to C:\programdata. (Again, adding a subfolder specific for your application or company)
Again, don't try to force the operating system to work against its rules. You will find yourself in trouble very often.

Related

SQLite database file location and environment

I have developed a little software for Windows few weeks now and got problems when trying to make proper installer for it.
I got spesific request that database file has to be in same folder where program is so user can take own backups every now and then.
When I install it (using Visual Studio 2012 and InstallShield Limited Edition project) it works in my main computer(W7 64-bit), my laptop(W8 64-bit) and my buddys Laptop(W8 32-bit) just fine.
My main computer runs program as it should, it uses database file from programs Database -folder(C:/Program Files (x86)/Program Name/Program Name/Database) and doesnt create additional db files but my laptop and my friends laptop create folder to
"C:/Users/User/AppData/Local/VirtualStore/Program Files (x86)/Program Name/Program
Name/Database" and use database from there.
Also I noticed that program crash on start on my other test computer that runs W7 32-bit and I made sure that .Net Framework was installed.
Connection string goes like: sqLiteConnection1.ConnectionString = "data source=.\\Database\\db";
Program's Platform target is set to Any CPU and it uses .Net Framework 4.5 if that helps anything.
Any ideas whats causing this and how I can fix it?
database file has to be in same folder where program is so user can take own backups
Danger Will Robinson! Non-admin users cannot modify files in the shared or Program Files folder. You are forcing users to run as Admins, or change the Program Files folder so non-Admins can modify it; both are serious security vulnerabilities.
If you install the database to the Programs folder, then the database is part of the install and not user data. This means that repairing or uninstalling the application will delete all user data. Users don't like that.
Your application should copy the application database to a user folder like Environment.SpecialFolder.ApplicationData and save all changes there. All users can modify and backup data from their own folders, no security vulnerabilities required. Also, when someone repairs or uninstalls the application, all users get to keep their data.
Your connection string is using current directory (.).
Create it dynamically with Assembly.GetExecutingAssembly().Location.

Access to SQL CE database in Program Files directory

I've read a bit that putting a.NET 2.0 SQL CE database in the program files directory where the application is installed is a bad idea. I'm running into the following error:
Access to the database file is not allowed. [ File name = C:\Program Files (x86)\MyCompanyName\MyApplicationName\MyCEDatabaseName.sdf ]
So I've heard, put it in Common Application files.... I'm not sure where that is, and I've read that the installer may drop the file there with the same permissions. I've also read that people have moved their file there and had issues.
Is it possible to change the ACLs of the file in the program files directory when the installer drops it there? I already have hooks into the application from the MSI to collect and set configuration options. I haven't found a good example of how to change the permissions on ONE file.
Then I've read to store it in the user's application data, but if you're installing the application 'for everyone' where will the file go?
Thanks for your time.... confused.
I assume you are using a MSI package. In this case you can use CommonAppDataFolder which is resolved to "C:\ProgramData".
However, this is also a per-machine location, so it requires the same privileges as Program Files. I think you heard about Application Data folder (AppDataFolder) which is a per-user location (something like "C:\Users\\AppData\Roaming"). It doesn't have permission problems.
If you want to use a per-machine location a solution is to use the LockPermissions table:
http://msdn.microsoft.com/en-us/library/aa369774(VS.85).aspx
This is a bit complicated because of all the permission flags. So if your setup authoring tool doesn't offer support for setting permissions, I suggest a simpler approach: use xcacls.exe as a custom action:
http://support.microsoft.com/kb/318754
This way all users can gain access to your database file.

Create a Setup File Windows.Net C#

I have created a windows application setup program, it needs to have a text file in the application folder. The file is also included while creating the setup.
Once the setup successfully completes and my program tries to modify the file based on user input, its simple throwing an exception.
I am using Windows 7 Home Premium OS.
Any suggestion/help will be great to overcome this issue.
This is normal on a Vista or Win7 machine. Or a properly secured XP machine for that matter. The normal install location for programs, like c:\program files\your company\your app, is read only for most users. UAC is a counter-measure to malware messing with programs.
You'll need to store the text file into a writable location, the AppData folder. In the Setup project, right-click "File system on target machine" and select User's Application Data Folder. Find that file back at runtime through Environment.GetFolderPath, passing Environment.SpecialFolder.ApplicationData. Or use "User's Personal Data Folder" if the user should be able to find it back easily through the Documents folder.
What exception is being thrown? It could be a UAC issue.

file write permission issue under "Program Files" folder

I am using inno setup to make a installation package for my application, and my application is written by C# + .Net 2.0 + VSTS 2008. Inno setup => http://www.jrsoftware.org/isinfo.php and I install my application under Program Files/Foo folder (Foo is my application name). My application is targeting to Windows Vista.
The issue I found is my program cannot write to the folder Program Files/Foo. And I need the permission of write to this folder in order to save some configuration files. The strange thing I notice is the folder Program Files/Foo is marked as readonly and I have checked all folders under Program Files are marked with read only, such as Office.
My questions are,
Why all folders are marked as read only under Program Files? It means we should not write to individual application folders under Program Files? If not, where should we write information to disk like user last selected configuration information of an individual application?
If we could write to individual application folders under Program Files, what is the solution? I do not want my application to Run As administrator to solve this issue, and if there are solution to write to this folder, I want to require minimal permission if possible.
You should write user specific config data to the Application Data folder for the current user, using the special folders enum and the Enivronment.GetFolderPath.
Best Practice is to not store config data in the Program Files folder. Instead, store your application's data in %AppData%\YourApplicationName. Depending on whether you want to store your config data per-user or in a shared common folder, use one of the following enums to get the folder path:
string userAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string commonAppData = Envrionment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
By default, Vista users do not run programs as Administrators and hence those programs have only read access to the folders under "Program Files". Users can change this behavior by disabling UAC and you could ask your users to do that, but in an office setting users might not have that option. That's why you use AppData instead -- applications can always read and write data to the AppData folder.
Information on UAC can be found at Microsoft's site. Although this page is fairly long, it's a starting point for understanding UAC:
http://msdn.microsoft.com/en-us/library/bb530410.aspx
A common solution would be to install configuration files to the Application Data folder i.e. like follows:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

What is the best way for on demand download and install of dlls in .NET?

We have an application that we wish to install just a basic shell for. As the users use it, it will download and install the necessary dlls for actions that need to take place (imagine a wizard application scenario with several possible paths). Currently, everything is installed for all possible paths through the shell app.
For about 3 months out of the year, the dlls used for the possible paths go through a high churn rate with updates, so we wish to start ensuring the users have the most recent version of these dlls. The idea is that after all their selections are made, we'd make a web check to see what dlls are required for their selection and check to make sure they have the most recent version of those files.
All of this we have a plan for on how to do it. The problem I'm fighting is what is the most appropriate way to "install" these files. ClickOnce is not an option...too much legacy stuff here. Our app is installed in "Program Files" which obviously has restrictions for writing random files into the program's install folder under Vista and later.
Right now I see the options as the following:
On install mark the install directory as writable for the "Everyone" group. I haven't actually tested to see if this would work yet, or if Vista does something different in this scenario.
Split the download portion out into a second app that we can have prompt for elevated privileges so that it can download and install these files.
I'm leaning towards the second option since that maintains the security aspect of the Program Files folder. Others in the group lean towards the first option because they just don't want to have to worry about things. Or is there some other option I'm missing?
The app is a .NET app, though it has some requirements of third party dlls that are not managed assemblies.
As long as the dlls you want to load are managed, there are several ways to do this.
One way is to designate an Environment.SpecialFolder path such as AppData and dynamically load assemblies into your appdomain from there. RssBandit does this for plugins, there is a special directory that loads dlls and searches for specific interface implementations, loads them into a temporary appdomain, and then calls them from the app. You could take this one step further by using an IoC library like ninject or structuremap.
you could also try MEF, the new extensibility framework coming out in C# 4.
Personally, I like what Firefox/xul apps do. It's a hybrid of your two proposed solutions, I suppose. They have an updater.exe that lives in the install directory. I assume that means that the install directory is made writable during install so that they can run the update application. However, having never deployed a application in this manner, I can't tell you how much of a headache (or not) it is.
An alternative which you haven't mentioned, and may not know about, is using the .Net download cache. When you attempt to load an assembly you can give it a code base to load from. If you set the codebase to a web url (i.e. http://mywebhost/mycoolapp/) .Net will download the assembly from that url if it's not found in the download cache. It will also grab the latest version of the assembly from the web url if there is one.
This approach can be a pain as you'll likely have to deal with CAS security issues if your app needs elevated permissions. However, it is nice not having to write code to download the latest versions of your assemblies for you. If you want more information, I can find some resources and give more detailed examples.
The way I handle it is to have an update.exe installed into program files next to the main .exe file.
Then, on app startup, I have the app download an xml file off of the web and save it in the App Data folder. This file contains the latest versions of the dlls and has a simple Filename, Version structure.
Run through the list of filenames and if you don't have the dll locally or you have an older version, then add the needed dll to an update list.
After you generate your update list. Fire off the Updater.exe with a command line list of the files to be updated. You don't have to write them to program files but I do. On Vista, my updater pops up the UAC prompt correctly (as it should to maintain Program Files' security).
The updater then downloads the files to Program Files and restarts the main app.
One problem with firing off the second app is that you have to give it a manifest with "AsAdministrator" set in it.
This isn't hard to do, but once the updater is done and retriggers the main app, it cannot start the main app with normal privileges. An exe running as administrator can only start other exe's as administrator also, even if "AsInvoker" is set in the manifest. I don't know why you can't restrict it back to normal rights...you can only elevate permissions for some reason...

Categories