I heard that Windows 7 restricts access to its registry, so that applications cannot write directly to it. Is this so? I am developing an application in C#, and I would like to be able to save things such as port settings, last file used, etc. between sessions. Is the registry still a good option, or is there another preferred means of doing this now? Thanks.
Access to the registry has been restricted since (at least) Windows NT 4. That does not mean that you cannot write to it; it just means that you cannot write to it everywhere. Normally, writing in HKEY_CURRENT_USER should still be possible.
The registry is still a good option for storing settings. However, you can also save yourself some work and use "application settings" instead, which are stored in an XML file in the user's profile folder. Here I asked what their advantage was over the registry, resulting in a great discussion of the pros and cons of each.
Related
I'm writing an NSIS script to upgrade an appliance between versions. The versioning and setup have gotten away from us a bit, as we have many versions in the field, and currently no easy way to upgrade from one version to another. So the first task I have is to write something that they can run on field machines to do everything necessary to bring them to the latest version.
The appliance runs on windows 7. it has 3 users. In the repository for the project there are 4 .msc files that contain group policies to set the appropriate settings for each of these. (computer, non-administrator, admin, appliance)
Is this the right way to go? in trying to power through learning NSIS, it seems easier to write the registry keys directly to HKU /user/... rather than the extra layer of indirection from GPO, given that I'm not doing any sort of distributed system using active directory (which I know approximately nothing about), and just have 3 static users on one static physical machine.
So concise questions:
Which approach makes more sense for my application? GPO files, or direct ntuser.dat editing on the various users.
if GPO makes sense, how do I apply an msc file inside NSIS? double clicking the file works in windows, but then you have the mmc open. oogly. is there a clean way to do it with NSIS?
How does a GPO in the registry under HKCU translate to a system wide policy? it seems to me that what's written to the registry is missing the critical information of which users it applies to (if it applies to a user or group).
Thanks in advance
.msc files usually contain data used by MMC and not policy data, perhaps you mean .adm template files? I don't think you can really apply a .msc file programmatically.
Direct registry editing is probably OK if your application just reads them normally on the other end, otherwise you might need to call gpupdate.
If your policy is stored under Software\Policies then entries in HKLM applies to everyone and entries in HKCU/HKU applies to that user. A normal user cannot change their policy under HKCU because they don't have write access. There is not really a concept of groups when using these keys.
Many questions on SO say "Windows developer guidelines" or "windows design guidelines" say that you shouldn't write temporary or program data to the Program Files area, but as far as I can tell none of them actually link to a piece of documentation that says as much. Searching the MSDN has yielded me no results. Windows will make the area read-only, so it can be enforced by the OS, but that doesn't mean developers didn't try to write there anyway (e.g., when porting older, XP and earlier based programs forward.)
I realize that it seems odd to ask about it this late into Windows development (since, as a commenter below pointed out, has been enforced by the OS for more than a decade), but a document that says so is sometimes necessary to satisfy people.
With that in mind, Does Microsoft have a document published stating we shouldn't write application data to the Program Files area, and if so, where is it?
From Technical requirements for the Windows 7 Client Software Logo Program:
Install to the correct folders by default
Users should have a consistent and secure experience with the default
installation location of files, while maintaining the option to
install an application to the location they choose. It is also
necessary to store application data in the correct location to allow
several people to use the same computer without corrupting or
overwriting each other's data and settings.
Windows provides specific locations in the file system to store
programs and software components, shared application data, and
application data specific to a user:
Applications should be installed to the Program Files folder by default. User data or application data must never be stored in this
location because of the security permissions configured for this
folder (emphasis added)
All application data that must be shared among users on the computer should be stored within ProgramData
All application data exclusive to a specific user and not to be shared with other users of the computer must be stored in
Users\<username>\AppData
Never write directly to the "Windows" directory and or subdirectories. Use the correct methods for installing files, such as
fonts or drivers
In “per-machine” installations, user data must be written at first run and not during the installation. This is because there is no
correct user location to store data at time of installation. Attempts
by an application to modify default association behaviors at a machine
level after installation will be unsuccessful. Instead, defaults must
be claimed on a per-user level, which prevents multiple users from
overwriting each other's defaults.
And I'm quite sure that there's similar stuff for every Windows version of the NT family going back to Windows NT 4 or even earlier.
See also this question.
Edit: the original link in this post to the Windows 7 Logo program exists no more. Here you find the current link to the Certification requirements for Windows Desktop Apps. See Section 10, Apps must install to the correct folders by default
In later versions of windows (Vista, 7 and of course server versions) access permission are restricted for "special folders" including "Program Files". Even if your program is elevated to have sufficient privileges to write to this folder it is still a bad idea.
I don't know of any guidelines that state this but there is a list of special folders and what they are meant for. The fact that there is a special folder for nearly all types of data I can image means there is no need to use the program files folder.
My application is a rather well behaved Windows citizen, so when I ported it to Windows Vista/7 I replaced my custom file format association code with support for the Default Programs API. However I ran into a problem when trying to make uninstaller for my application - there seems to be no way to remove file format associations via Default Programs API.
I tried to call IApplicationAssociationRegistration::ClearUserAssociations but it actually removes all associations, including the ones for other applications - completely restoring default state of the OS (which is of course unacceptable).
I tried to call IApplicationAssociationRegistration::SetAppAsDefault to return file format associations to the previous "owner" - but it does not help, because my application handles many unique file formats which the OS does not support and there is no previous "owners". And Windows does not allow to pass empty strings to SetAppAsDefault...
So what do I do? Any good solutions?
I think that you are using the Default Programs API in the wrong way. If I understand correctly the default programs functionality was added by Microsoft due to legal requirements to replace Internet Explorer as the default browser. It offers another set of functionality than the normal file associations used by aplications. If you just have a simple file association to register, I'd suggest you stick to the old behaviour.
From MSDN:Default Programs (Windows):
Default Programs is primarily designed for applications that use standard file types such as .mp3 or .jpg files or standard protocols, such as HTTP or mailto. Applications that use their own proprietary protocols and file associations do not typically use the Default Programs functionality.
Side note: All the considerations below apply even if you modify directly the file associations in the registry instead of using the Default Programs API.
On first run, your application should collect the previous owners of all the file types for which one exists, through IApplicationAssociationRegistration::QueryCurrentDefault and store them in storage your app owns.
On uninstall, your application should use IApplicationAssociationRegistration::SetAppAsDefault to attempt to restore any file association it still owns to the previous owner it has. For associations your app still owns, but don't know previous owners, go to the HKCR registry and delete the corresponding extension, protocol or MIME type entry. Don't touch any associations your app is not the current owner - you'll be overwriting the user's choice.
I certainly wish that the batched backup on first run and cleanup on uninstall were provided as a single API call by the Default Programs API, but until they decide to generalize that behavior for all apps, you're on your own.
Note that the cleanup your application executes on uninstall will be specific for the uninstalling user. Any other users that might have used the application and changed their defaults will not be cleaned up.
You can automate the cleanup for each user by adding a simple per-user task that executes the steps above in the Task Scheduler. The task will be scheduled to execute once and then removes itself from the user task scheduler. The only potential problem with that approach is that since you don't know how many users there will be, it's impossible for you to know when to remove the dll for that task from the machine. Then again, if you leave that dll in the ProgramData folder, it's not a big deal.
The correct code for associating your file extension with an application, is using the Windows Registry settings. Typically this is done to the entire machine (regardless of user) using the HKEY_LOCAL_MACHINE\SOFTWARE\Classes registry hive, which is also accessible more conveniently through the HKEY_CLASSES_ROOT alias (registry shortcut).
Your process involves three steps:
Saving the "old" settings, before installing your application (BTW, it's nice that you are doing that. Many applications simply remove the mapping altogether!)
Creating your own associations. A good example on how to perform this is at Modifying File Associations With Registry Editor. A thorough explanation is on MSDN:
When uninstalling, recover the saved "old" settings from step (1), and rewrite the installed values with these original ones. In case there were no "old" settings, a good citizenship would mean simply deleting the class key altogether from the registry.
One tool to assist in debugging and seeing how class (extension) mappings change is at FileAsoc Windows File Association Editor. It lets you recover file extensions while debugging your application. The webpage also gives a short explanation of how exactly the values are stored.
Hope this helps!
Instead of making the file associations in your app, make them in the installer. Using WiX you can create an installer that sets file associations on install and will remove them on uninstall
I work on a vb6 application which is having problems with Vista, for the obvious reasons (writing to program files, and other things that are no longer allowed by default).
Where should I store application data or user's saved files?
Do I need priviledges to create folders and files, there, too?
What other common actions will cause problems?
The program has an updater which must download and register files, how do I elevate priviledges when this occurs?
Some of these questions have obvious answers, but I want to get the obvious stuff right.
Depending upon what you are doing, you might be in for a world of pain. There are no hard and fast answers to any of those questions, but from someone who is going through the same issues right now, here's what I know.
1) Where should I store application data or user's saved files?
This depends on what you are wanting to do. If you want them per user, store them in Users/AppData, if you want them for all users, store them in Common/AppData
If SHGetFolderPath(0, CSIDL_COMMON_APPDATA, -1, SHGFP_TYPE_CURRENT, sTempPath) = 0 Then
sCommonAppdata = Left$(sTempPath, InStr(1, sTempPath, Chr(0)) - 1) & "CompanyName\AppName"
End If
Change that to CSIDL_APPDATA for the Users AppData directory. Note: These map to totally different places on the filesystem for XP and Vista so when you are debugging prepare to look in different places.
2) Do I need priviledges to create folders and files, there, too?
You need Adminsitrator access to write anything in Program Files, if at all possible don't do it! We are currently running into issues that the API's for VB and the standard API's behave differently on files in Program Files.
3) What other common actions will cause problems?
There are lots of hidden gotchas. Just to name a few, you cannot communicate through IPC or Named Pipes to other applications (we have a Service that we were talking to through a Tray Notification Icon and that had to be completely re-written). Anything were you see a UAC notification is very difficult. Also you cannot write to anything in the Registry in LOCAL_MACHINE without Administrator, so you either have to stick to LOCAL_USER or raise credentials (see below).
4) The program has an updater which must download and register files, how do I elevate priviledges (sic) when this occurs?
Good luck with this, I highly recommend that you don't write it in VB6, like I said, the VB6 file api's appear to access files differently from the standard API's. If you need to elevate privileges see this post that someone kindly helped me with.
In the sort term turning off UAC and installing the ActiveX installer server will help. Long term you need to put data and configuration information in the users directory under \users or in \programdata.
In the short run it might not be necessary at all to modify your application, because
Vista comes with a set of compatibility options to allow legacy applications to run. This includes file and registry virtualization, a feature which basically redirects write operations to protected folders such as C:\Program Files to a virtual location only visible for the specific application running in a compatibility mode.
Some more details are mentioned in this article: How To Manage Windows Vista Application Compatibility in Dr. Dobb's.
Karl Peterson wrote a nice article on where to store user data & app data, with a VB6 class that retrieves the location of the special paths for you.
As a developer, tools that store configuration/options in the registry are the bane of my life. I can't easily track changes to those options, can't easily port them from machine to machine, and it all makes me really yearn for the good old days of .INI files...
When writing my own applications, what - if anything - should I choose to put in the registry rather than in old-fashioned configuration files, and why?
Originally (WIN3) configuration was stored in the WIN.INI file in the windows directory.
Problem: WIN.INI grew too big.
Solution (Win31): individual INI files in the same directory as the program.
Problem: That program may be installed on a network and shared by many people.
Solution(Win311): individual INI files in the user's Window directory.
Problem: Many people may share a windows folder, and it should be read-only anyway.
Solution (Win95): Registry with separate sections for each user.
Problem: Registry grew too big.
Solution (WinXP): Large blocks of individual data moved to user's own Application Data folder.
Problem: Good for large amounts of data, but rather complex for small amounts.
Solution (.NET): small amounts of fixed, read-only data stored in .config (Xml) files in same folder as application, with API to read it. (Read/write or user specific data stays in registry)
Coming at this both from a user perspective and a programmers perspective I would have to say there really isn't a good exceuse to put something in the registry unless it is something like file associations, or machine specific settings.
I come from the school of thought that says that a program should be runnable from wherever it is installed, that the installation should be completely movable within a machine, or even to another machine and not affect the running of it.
Any configurable options, or required dlls etc, if they are not shared should reside in a subdirectory of the installation directory, so that the whole installation is easily moved.
I use a lot of smaller utility like programs, so if it cant be installed on a usb stick and plugged into another machine and just run, then its not for me.
When - You are forced to due to legacy integration or because your customer's sysadmin says "it shall be so" or because you're developing in an older language that makes it more difficult to use XML.
Why - Primarily because the registry is not as portable as copying a config file that is sitting next to the application (and is called almost the same).
If you're using .Net2+ you've got App.Config and User.Config files and you don't need to register DLL's in the registry so stay away from it.
Config files have their own issues (see below), but these can be coded around and you can alter your architecture.
Problem: Applications needed configurable settings.
Solution: Store settings in a file (WIN.INI) in the Windows folder - use section headings to group data (Win3.0).
Problem: WIN.INI file grew too big (and got messy).
Solution: Store settings in INI files in the same folder as the application (Win3.1).
Problem: Need user-specific settings.
Solution: Store user-settings in user-specific INI files in the user's Window directory (Win3.11) or user-specific sections in the application INI file.
Problem: Security - some application settings need to be read-only.
Solution: Registry with security as well as user-specific and machine-wide sections (Win95).
Problem: Registry grew too big.
Solution: User-specific registry moved to user.dat in the user's own "Application Data" folder and only loaded at login (WinNT).
Problem: In large corporate environments you log onto multiple machines and have to set EACH ONE up.
Solution: Differentiate between local (Local Settings) and roaming (Application Data) profiles (WinXP).
Problem: Cannot xcopy deploy or move applications like the rest of .Net.
Solution: APP.CONFIG XML file in same folder as application - , easy to read, easy to manipluate, easy to move, can track if changed (.Net1).
Problem: Still need to store user-specific data in a similar (i.e. xcopy deploy) manner.
Solution: USER.CONFIG XML file in user's local or roaming folder and strongly-typed (.Net2).
Problem: CONFIG files are case-sensitive (not intuitive to humans), require very specific open/close "tags", connection strings cannot be set at run-time, setup projects cannot write settings (as easily as registry), cannot easily determine user.config file and user settings are blown with each new revision installed.
Solution: Use the ITEM member to set connection strings at runtime, write code in an Installer class to change the App.Config during install and use the application settings as defaults if a user setting is not found.
Microsoft policy:
Before windows 95, we used ini files for application data.
In the windows 95 - XP era, we used the registry.
From windows Vista, we use ini files although they are now xml based.
The registry is machine dependent. I have never liked it because its getting to slow and it is almost imposible to find the thing you need. That's why I like simple ini or other setting files. You know where they are (application folder or a user folder) so they are easy portable, and human readable.
Is the world going to end if you store a few window positions and a list of most recently used items in the Windows registry? It's worked okay for me so far.
HKEY-CURRENT-USER is a great place to store trivial user data in small quantities. That's what it's for. It seems silly not to use for its intended purpose just because others have abused it.
Registry reads and writes are threadsafe but files are not. So it depends on whether or not your program is single threaded.
Settings that you want to have available in a user's roaming profile should probably go in the registry, unless you actually want to go to the effort of looking for the user's Application Data folder by hand. :-)
If you are developing a new app and you care about portability you should NEVER store data in windows registry since other OS don't have a (windows) registry (duh note - this may be obvious but gets often overlooked).
If you're only developing for Win platforms ... try to avoid it as much as possible. Config files (possibly encrypted) are a way better solution. There's no gain in storing data into the registry - (isolated storage is a much better solution for example if you're using .NET).
Slightly off-topic, but since I see people concerned about portability, the best approach I've ever used is Qt's QSettings class. It abstracts the storage of the settings (registry on Windows, XML preference file on Mac OS and Ini files on Unix). As a client of the class, I don't have to spend a brain cycle wondering about the registry or anything else, it Just Works (tm).
http://doc.trolltech.com/4.4/qsettings.html#details
Personally I have used the registry to store install paths for use by the (un)install scripts. I'm not sure if this is the only possible option, but seemed like a sensible solution. This was for an app that was solely in use on Windows of course.
Usually, if you don't put settings in registry, you use it mostly to get current Windows settings, change file associations, etc.
Now, if you need to detect if your software is already installed, you can make a minimal entry in registry, that's a location you can find back in any config. Or search a folder of given name in Application Data.
If I look at my Document and Settings folder, I see lot of softwares using the Unix dot notation for setting folders:
.p4qt
.sqlworkbench
.squirrel-sql
.SunDownloadManager
.xngr
.antexplorer
.assistant
.CodeBlocks
.dbvis
.gimp-2.4
.jdictionary
.jindent
.jogl_ext (etc.)
and in Application Data, various folders with editor names or software names. Looks like being the current trend, at least among portable applications...
WinMerge uses a slightly different approach, storing data in registry, but offering Import and Export of options in the config dialog.
I believe that Windows Registry was a good idea, but because of great abuse from application developers and standard policies not encouraged/mandated by Microsoft grew into an unmanageable beast. I hate using it for the reasons you've mentioned, there are however some occasions that it makes sense using it:
Leaving a trace of your application after your application has been uninstalled (e.g. remember user's preferences in case the application is installed again)
Share configuration settings between different applications - components
In .NET there really is NOT ever a need.
Here are 2 examples that show how to use Project proerties to do the this.
These examples do this by Windows User Project Properties, but the same could/can be done by Application as well.
More here:
http://code.msdn.microsoft.com/TheNotifyIconExample
http://code.msdn.microsoft.com/SEHE
(late to the discussion but) Short Answer: Group Policy.
If your customer's IT department wants to enforce settings related to Windows or the component(s) you're writing or bundling in, such as a link speed, or a custom error message, or a database server to connect to, this is still typically done via Group Policy, which makes its ultimate manifestation as settings stored in the registry. Such policies are enforced from the time Windows starts up or the user logs in.
There are tools to create custom ADMX templates that can map your components' settings to registry locations, and give the administrator a common interface to enforce policies (s)he needs to enforce while showing them only those settings that are meaningful to enforce this way.