When we create a SetUp & Deployment project for our application in .net, the default folder for our application to be installed is being set as C:\Program Files.....
Our application will run perfectly if we are using a Windows XP machine. But if we are using a Windows Vista or Windows 7 machine, the application wont run perfectly, especially if we are performing any file operations in our application...
Can anyone find a solution for this problem? Is there any means to penetrate this User Account Control and File Access Controls of Windows 7? or can any1 give a choice to change the default installation folder from [ProgramFilesFolder]\[Manufacturer]\[ProductName] to some other folder?
If your application writes to any files under its install folder (i.e. under Program Files if default path is used), then it is badly written. You shouldn't try to circumvent OS security mechanisms to protect the user from badly written apps; you should rather fix your app so that it works correctly.
And it is, of course, not a .NET issue at all. Any application doing the same thing, no matter which language/framework it's written in, will have the same problem.
You should still install your application in Program Files folder. there are good reasons to have it there - a single copy for all users, in a well known locked place where nobody but an admin can tamper with your binaries.
However, any file operation you are doing should be in one of the standard Windows locations for user-writable files. There are several such folders, depending on the file usage model. You can read more about these in the following SO questions :
My winform app uses xml files to store data, where should I store them so Vista users can write to them?
Vista and ProgramData
Data shared among all users should go in C:\ProgramData (use Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) to find out where it actually lives -- it can be different between Windows versions).
Data specific to the user should be in SpecialFolder.ApplicationData. If the user has a roaming profile, this is shared between machines.
Data specific to the user that's also specific to the machine should be in SpecialFolder.LocalApplicationData.
If you really need to put something in your program's installation directory, you need to do this with Administrator privileges.
You should either do this by prompting for elevation the first time that the program is run. Preferably, you should do this during installation (because you're already elevated).
First of all, you should not set your app to install under C:\Program Files\..., you should instead set it to %PROGRAMFILES%\... While these will usually equate to the same thing, they can be different on a 64 bit system, or they can be wildly different if the system has been set that way.
As already mentioned, don't try to circumvent the UAC, it is there for a reason, and your program is no more special than any other program on the system. Instead what you should do is set your app manifest to demand administrative level permission upon launch (which if granted bypasses the file system virtualization, although the user can decline it or possibly not even have the rights to launch something as admin). The other thing you can do is set the ACLs on the folder that your app sits in, and give all users on the machine read/write access to that folder (this would have to be done at install time).
Or you can do things the proper way and store your data files in the %APPDATA% folder, which you have full rights to, although these folders are specific to each individual user of the system.
I'd suggest start here http://channel9.msdn.com/pdc2008/PC51/
That will give you a good foundation.
Related
I want to track a setting system-wide on the target machine- it is a run time counter that keeps track of how many times my client runs my software. I decided to put this value in the registry, but I really want to track how many times it is run for the whole system, not just for the current user account.
I would expect to use HKLM to track this at a machine level, but UAC doesn't like this nowdays.
Is there a correct way to read and write a setting that is machine-wide?
HKLM isn't for this type of use (since Windows XP at least).
Use the %PROGRAMDATA% folder instead (which you can also get via the WinAPI function SHGetKnownFolderPath with FOLDERID_ProgramData (SHGetFolderPath with CSIDL_APPDATA on Windows versions prior to Vista). It's specifically designed for application data that is global to all users of the machine. (On Windows 7, this is the C:\ProgramData folder by default.) Your application should create a directory beneath there and store the counter information in a file in that location instead.
(It also means you don't have to defeat the purpose of UAC by allowing public write access to the registry in inappropriate locations.)
From Environment.SpecialFolder Enumeration:
CommonApplicationData The directory that serves as a common repository for application-specific data that is used by all users.
Have a "CommonApplicationData\Your Company Name\Your Product Name" folder created in your setup program and change the ACL for the folder to allow limited user full control permissions (the inherited permission is read only for limited users). You can do this via the LockPermissions MSI table, or if your setup program does not support LockPermissions, create a custom action to change the ACL.
You also need to handle potential edit conflicts created by fast user switching.
I want to know what is the actual difference between Application and User scope in Settings configuration for vs projects.
Is the only difference the fact that if I select Application, I can't use Settings.MyProperty as a setter, but I have to use Settings["MyProperty"] instead?
How would using the User scope affect the program otherwise, if the config file is located at my application root?
User scope means each user gets their own copy, the settings are stored in the users profile folders and your App can Save those settings without Admin privileges.
If you change an Application setting (using Settings["MyProperty"]) and call Settings.Save() you will have to be running as Admin because the changes are saved to MyApplication.exe.config . And changes apply to all users.
Your best bet is to use the 'User' setting because with the newer operating systems Windows doesn't like you reading and writing to files that are local to your executable, this looks suspicious due to the awareness of viruses. So Windows likes you to read and write to designated safe areas which I believe happens in some application data area that the operating system keeps track of. If you set the scope to 'Application' it may try to write this data to the local config file(which is why you need to run with admin privileges) and with the operating systems becoming more locked down there may still be issues doing this. Your app may work in XP like this but anything newer might not work, especially when apps run in the 'c:\Program Files' folders...
My application needs to, like most, store data. The application was previously used on XP only where it would store the data in Program Files. Now that our customers are moving to Windows 7 I had to upgrade it so that it stored the data in a new folder. I opted for the ApplicationData folder as I thought I would be allowed access without needing UAC at all.
Now on some Windows 7 machines this is fine, but on others access to the folder fails, presumably because of permissions, but when ran with Administrator privelidges the program works fine.
Am I using the wrong folder or are these cases outliers? In either case what is the best practice for this kind of thing?
I am using the following C# SpecialFolder to get the AppData folder location.
System.Environment.SpecialFolder.ApplicationData
System.Environment.SpecialFolder.ApplicationData is per-user and roams. That doesn't sound like what you want. You appear to want machine wide settings and so should use System.Environment.SpecialFolder.CommonApplicationData.
Because CommonApplicationData is shared between all users, the default access control is limited. By default standard users cannot write in this location. The recommended practise is to create a sub-folder of CommonApplicationData at installation time and assign it suitably permissive access control settings.
David is right.
As far I know, there's also some difference if you deploy your app via ClickOnce or Installer: the first allows a few subset of permissions than the normal installer.
I must confess I'm not an expert on that.
Of sure, Program Files is the worst place to store data, even since XP.
Application2 was orginally developed an application for WinXP. Now I have to contend with User Account Control (UAC) on Win7. The Application2 runs fine on Win7 as long as the user is logged into an Administrator account and they select "Run as administrator." However, I am trying to evaluate whether it is possible to refractor Application2 so that it does not require an Administrator account and "Run as administrator." I would also like to avoid any dialog boxes requiring users to make a choice if possible.
Application2 features that currently require "Run as administrator"
Create System Data Sources (ODBC)
Read/write/delete registry keys
Copy/delete files in C:\Program Files\MyApp
Encypt/decrypt files in C:\Program Files\MyApp
Start .exe processes located in a shared folder on a remote machine
Start VBScript processes that install Office Add-ins and read/write/delete registry keys
Copy/delete/modify files in C:\Program Files\MyApp\MyData
Number 6 can be solved by relocating this folder to My Documents (its location is stored in the registry*), or granting the user "Full control" permissions to C:\Program Files\MyApp\MyData, or letting Win7 make the necessary modifications in the VirtualStore folder.
Numbers 3 and 4 is more difficult to deal with because Application1 has to read files in C:\Program Files\MyApp. Application1 will not be using "Run as administrator," and I need to do more research to figure out how the VirtualStore folder can be used to bridge the gap between Application2 and Application1.
As for the other points, I am trying to figure out options:
Please let me know if/how it is possible to perform these actions under a non-Administrator user account and without "Run as administrator."
Please let me know if any of the actions are impossible without being an Administrator.
Feel free to point out any technical mistakes that I may have made in the contents of this question.
Again, I am trying to avoid dialog boxes during application runtime.
*Thinking out loud here: I would need to delete C:\Program Files\MyApp\MyData after copying to C:\My Documents\MyData, and I would need to modify the registry key storing the folder path, maybe these steps could be done during installation.
Discoveries
On Windows 7, even without "Run as administrator" you can:
Create/delete User Data Sources
Create/modify/delete files in C:\Users\Public\Documents or C:\Users\currentuser\Documents
Create/delete registry keys in HKEY_CURRENT_USER
Furthermore, I believe it is dangerous to have a Windows 7 application without a UAC Application Manifest file. Because, if you don't have one, Windows 7 decides for you whether to run the application in Compatibility Mode or not. If you have one, you can specify how your application needs to run.
No, you can't do these things without getting elevated. The point of UAC is not to stop you from doing this, it is to let the user know that you're about to do this. An obvious and valuable property of UAC is that it doesn't provide a backdoor to do these things anyway without the user knowing about it. This is not a problem, it is a feature.
What you describe doesn't strike me as something that needs to happen frequently. This should not wear out the user. If that's an issue, you can run it from a scheduled task using an admin account.
The best thing to do is to change your application - only slightly, mind you - so that it will run as a non-elevated user. To help you do that, I have to point out some subtleties.
For example, point 1, "read and write registry keys", is overly general. Applications that are non elevated can and do read and write registry keys with no problem at all. The restriction is that you can't write registry keys in HKLM. So you can avoid UAC issues if you change your code to use a key under HKCU, or if you refactor some of your code into an admin/config/setup app that runs elevated and writes keys to HKLM, and an ordinary app that reads those keys but never writes them.
Point 2 and 3 are both "can't write to anything under Program Files." Change your code so that the files you need to copy/delete/encrypt/decrypt are not under Program Files. AppData is a popular (per user) location for this.
Stay away from the whole virtualization thing and deliberately trying to use the Virtual Store. It confuses users tremendously. Instead, gain a firm understanding of the behaviours that non-elevated apps can't execute, and adjust your code to perform the (very similar) replacement behaviours, such as using HKCU instead of HKLM or AppData instead of Program Files.
I have a C# app that creates a settings file for itself to store the current state of certain visual elements. This app works just fine on any machine that isn't running Windows 7, but on those machines we get an error that the settings file can't be created because the user doesn't have permission. Now, I could fix this issue by going to each computer, logging in as the administrator and giving the user read and write access on the program folder for the application that we've installed, but there has to be a better way.
It seems like in XP, you got write access on the folders you created by default, but that isn't the case anymore. Is there a setting I need in the setup package to make this work?
The point is that you shouldn't be storing settings files in the program folder. Microsoft have advised against this for a long time, but started making things stricter with Vista IIRC.
Use Environment.SpecialFolders.ApplicationData (etc) to find the most appropriate place to put settings. Or use the .NET settings infrastructure which does this automatically for you.
are you trying to create files in the installation folder? you should be using the user data folder for data and not the installation folders. Use the Environment.SpecialFolders.ApplicationData folder to get a folder you can write to.
You're probably running as an administrator on your non-Windows 7 machine which an write anywhere. Be sure to save any per user instance data in their AppData folder (roaming if it should follow them from computer to computer, or local if its a cache or local to taht machine only). If you need to share settings between users, use the C:\ProgramData folder with the appropriate permissions.
A program shouldn't try to store settings in its installation directory.
Be sure to use the SpecialFolders along with Environment.GetFolderPath to get the right locations needed. You should never hard code paths because they can be different between versions AND languages. (I know in the German version of XP it wasn't Program Files but Programme!)
this app works just fine on any machine that isn't running Windows 7
Wrong! It only works on those machines if you run as administrator. I think you'll find your program is broken on Windows XP as well if you try to run it on just about any business computer rather than a home computer.
Instead, this kind of information needs to go in one of the special Application Data folders.
This is a security flaw in your program because your program is writing information to the program directory (which is, and should be, protected.) If it's a situation of correcting the root cause, consider using the SpecialFolder enumeration or the static members on Application like like CommonAppDataPath to write your information to a more appropriate location.
Assuming the typical approach to writing a file via a path, this is a trivial fix and there's no good "expediency" reason to not correct the root cause. If you're not sure about how to manipulate the path, consider using Path.Combine(). It does it for you.
In general, you shouldn't be writing program data to any folder underneath Program Files (even if you created the folder). You should use the Environment.GetFolderPath(...) to figure out where to put your application specific data. You can pass in one of many enums defined here -- you probably want Environtment.SpecialFolder.CommonApplicationData
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
I do not see how any of this is an actaul answer. I need to be able to write a report and have it saved the users documents folder the same folder I used to read the xml files I am writing the report from.