I'm working hard on making my product work seamlessly on Windows 7. The problem is that there is a small set of global (not user-specific) application settings that all users should be able to change.
On previous versions I used HKLM\Software\__Company__\__Product__ for that purpose. This allowed Power Users and Administrators to modify the Registry Key and everything worked correctly. Now that Windows Vista and Windows 7 have this UAC feature, by default, even an Administrator cannot access the Key for writing without elevation.
A stupid solution would, of course, mean adding requireAdministrator option into the application manifest. But this is really unprofessional since the product itself is extremely far from administration-related tasks. So I need to stay with asInvoker.
Another solution could mean programmatic elevation during moments when write access to the Registry Key is required. Let alone the fact that I don't know how to implement that, it's pretty awkward also. It interferes with normal user experience so much that I would hardly consider it an option.
What I know should be relatively easy to accomplish is adding write access to the specified Registry Key during installation. I created a separate question for that. This also very similar to accessing a shared file for storing the settings.
My feeling is that there must be a way to accomplish what I need, in a way that is secure, straightforward and compatible with all OS'es. Any ideas?
Do you have to have it in the registry? If not, put it into a simple file, writable by everyone. Writing to HKLM requires additional privileges for a very good reason.
I'm new to here (otherwise i would've left a comment) and i'm not a windows guru, but...
imho the premise is wrong:
there's a reason if a non-elevated user cannot modify registry keys or directories read by all users (like Users\Public by default)
i think that allowing any users to modify a small set of global application settings may be disruptive for the experience of the other users that didn't expect their settings to be modified
on the other hand i don't know your use cases...
could you please specify why all users should be able to modify these settings?
and if indeed all users have to be able to do it... why can't you make these settings user-specific?
Related
I am writing desktop programs for windows and when I need to put some program to start automatically I always use one of those options:
1 - Put a shortcut to the program in the startup group
2 - Create a value key on Windows Registry ("SOFTWARE\Microsoft\Windows\CurrentVersion\Run")
Which of this options is a best practice?
It depends on how much weight you would apply to the following questions:
As a user, should I be able to deactivate the automatic startup easily, even temporarily?
As a user, should I get the feeling that the developer trusts me to know what I'm doing?
Clarification:
If I have a shortcut in the AutoStart folder, I know that I can quickly disable this part by myself and the developer trusts me to do this.
If I don't have this visual clue, I have to actively look for it using more-or-less arcane tools (speaking from experience here).
If the automatic startup is essential for the correct function of the program, by all means, put it somewhere I can't get to it. But if it's a nice-to-have thing, like a "quickstarter", then please don't.
My application currently writes files to its installation directory which means Program Files isn't a valid option (I know this isn't ideal). But I would also prefer my installer (Inno) not to require admin rights i.e. no UAC; I think Google Chrome does this.
Which common location would make sense to default to with both these restrictions in mind?
If you really want to make a per-user installer that does not require admin permissions, the correct settings to use are:
[Setup]
PrivilegesRequired=lowest
DefaultDirName={userpf}\YourAppName
Note that (addressing Glytzhkof's concerns) this is a local folder, not a roaming folder. If you want settings to roam then you will still need your application to keep them in (your language's equivalent of) the {userappdata}\YourAppName folder. Regardless, the user will have to separately install the software on each machine that they intend to use it on (but this is typically the best option anyway).
Some of the downsides of making a per-user application are:
You cannot use admin permissions when installing. In particular this means that you cannot install many other components (runtimes, libraries, etc) that you might have wanted to use in your application. You also can't use features like regserver and restartreplace. (This doesn't necessarily mean that you cannot still use these components, just that it's a larger hassle if the user does not already have them installed.)
If a single machine has multiple users (common for families and in some workplaces) then they will have duplicate independent copies of your application, which have to be individually upgraded by each user. This particularly annoys IT departments as they prefer doing central upgrades, and if your app is large it may waste disk space.
If the reason you don't want to make a normal {pf} based application is simply that you want to be lazy and store settings files in the program's folder, then it's probably better overall to rethink this decision. It's not hard to do it "right".
There are basically 3 types of files: 1: user data, 2: application settings, and 3: binaries. Plus a few exceptions. I assume Harry is suggesting to write to a user's application data folder with configuration and settings files, and not the whole application. Don't ever put binaries or data here, but do save settings files here.
The whole concept of "roaming files" is a bad idea in my opinion. It clogs your userprofile and increases logon time on each computer and causes all kinds of synchronization issues when people leave multiple machines logged on simultaneously for weeks at a time. The whole roaming concept works only in theory in my opinion - but it depends on user discipline and application quality in its data management. Rarely edited and mergeable files can work, if the application is good. I have seen it work well for spell checker custom dictionaries and similar. The real solution is client/server applications with back-end databases for the purpose of persisting settings. Everything else will eventually fail - if it's a light weight app that might not matter.
User data should be saved to the "My Documents" location only. and only a few configuration settings should roam. If a network is set up to allow "My Documents" to roam, the system administrator should be shot immediately :-). It must be a server share accessible regardless of the computer the user is logged on to.
I've flown off the handle here and answered too many questions you didn't ask. Just hate seeing people head for problems they might not know about. If you have a super small application that is basically "portable" as we call it in deployment. That means an application where you can run off a single folder on a USB stick, then save everything in User data, and keep the application small and lightweight with a single settings file and a binary. No UAC or admin rights should be needed.
Reason for this question:
http://nsis.sourceforge.net/Reference/SetShellVarContext
and
http://forums.winamp.com/showpost.php?p=2326213&postcount=5
I am kind of puzzled here... what is actually most current way to handle this Windows specific installation/uninstallation feature, so that installer/uninstaller would automatically write, for example, registry to right place ( if Admin, then to HKLM, if specific user, then to HKCU )?
What makes me worried here is that the built-in command is pre-NSIS 2.0 introduced feature ... but
MultiUser.nsh
is pretty updated and from Joosts comment I start to think it ( using SHELL_CONTEXT ) might be better solution. Could it be right assumption here?
My goal is to make current Installer more flexible for future changes and development needs, including multi-user capabilities ( if, for example, Windows Certification requieres such support ). Ability to automatically depend on HKLM/HKCU, but not statically only on HKLM is pretty good think, right?
Maybe I just mixing File handling in current User context and Registry handling in current User context?
Any guidelines here would be much appreciated.
MultiUser.nsh uses RequestExecutionLevel and SetShellVarContext.
SetShellVarContext controls where the shell special folders like $appdata resolve to and it also controls the SHCTX pseudo registry root key. This means that you should write uninstall info and file extension registration under the SHCTX key if you wish to support per-user and all users install modes in the same .exe
I have an application that has to support modifying some registry data depending on the kind of 'installation' that is desired. At present, I have no problems hard-coding to either get elevation and do the changes to the entire local machine, but it is far from nice as ideally, I would also like to support per-user installations. I could hardcode that, but then I lose the local-machine stuff. To be precise, the changes in question involve file association changes, COM stuff etc.
How can I properly support both usage scenarios? Currently I use a set of ON/OFF checkboxes for the variety of associations.
Should I change this meaning on, for example, a MachineInstall file existing in my apps directory, and if not assume User install?
Is it an expected/valid/whatever usecase to say that someone might want to do some things for the entire machine, and some things only for the user? (E.g. mixing of the two.)
Or should I change the entire UI, move away from checkboxes and move to some sort of combobox going 'None/User/Local'? Then again, I think this might have some sort of breakage once you involve multiple users and combinations.
To give an indication, I personally expect the application in question to have its uses for everyone on a computer and as such lean towards the Local-Machine as a 'default', if that makes any sort of difference.
I am likely overthinking the matters quite a bit, so any and all input is very much appreciated. :)
P.S.
Now, someone is probably going to say 'do not do all that stuff from your app, do it from the installer instead'. And they probably have a point, but the point is to allow easy changing of these settings from within the application. To top it off, I am not using .MSI install packages because they make working with 32/64-bit specific executables a disaster requiring merge modules, spawning other MSI's depending on the situation, and so forth (I forgot the details last time I dug into it and forgot about the matter). I don't have that knowledge, nor the time to learn all the intricacies of MSI installations, so it is out for as far I am concerned. To boot, my application is perfectly capable of functioning without any of those registry entries being present, and that is by design. In a way, one might compare it to be like Process Explorer from Sysinternals, which does not require an installer, but can be unzipped and take over the task manager etc without a problem if a user wants, or simply run stand-alone.
I would like to create events for certain resources that are used across various processes and access these events by name. The problem seems to be that the names of the events must be known to all applications referring to them.
Is there maybe a way to get a list of names events in the system?
I am aware that I might use some standard names, but it seems rather inflexible with regard to future extensibility (all application would require a recompile).
I'm afraid, I can't even consider ZwOpenDirectoryObject, because it is described as needing Windows XP or higher, so it is out of question. Thanks for the suggestion though.
I am a little unsure about shared memory, because I haven't tried it so far. Might do some reading in that area I guess. Configuration files and registry are a slight problem, because they do tend to fail with Vista due to access problems. I am a bit afraid, that shared memory will have the same problem.
The idea with ProcessExplorer sounds promising. Does anyone know an API that could be used for listing events for a process? And, does it work without administrative rights?
Thank you for the clarification.
There is not really a master process. It is more of a driver dll that is used from different processes and the events would be used to "lock" resources used by these processes.
I am thinking about setting up a central service that has sufficient access rights even under Vista. It will certainly complicate things, but it might be the only thing left facing the problems with security.
No, there is not any facility to enumerate named events. You could enumerate all objects in the respective object manager directory using ZwOpenDirectoryObject and then filter for events. But this routine is undocumented and therefore should not be used without good reason.
Why not use a separate mechanism to share the event names? You could list them in a configuration file, a registry key or maybe even in shared memory.
Do not mix up the user mode ZwOpenDirectoryObject with the kernel mode ZwOpenDirectoryObject -- the kernel mode API (http://msdn.microsoft.com/en-us/library/ms800966.aspx) indeed seems to available as of XP only, but the user mode version should be available at least since NT 4. Anyway, I would not recommend using ZwOpenDirectoryObject.
Why should configuration files and registry keys fail on Vista? Of course, you have to get the security settings right -- but you would have to do that for your named events as well -- so there should not be a big difference here. Maybe you should tell us some more details about the nature of your processes -- do they all run within the same logon session or do they run as different users even? And is there some master process or who creates the events in the first place?
Frankly, I tend to find the Process Explorer idea to be not a very good one. Despite the fact that you probably will not be able to accomplish that without using undocumented APIs and/or a device driver, I do not think that a process should be spelunking around in the handle table of another process just to find out the names of some kernel objects. And, of course, the same security issues apply again.
ProcessExplorer is able to enumerate all the named events held by some specific process. You could go over the entire process list and do something similar although I have now clue as to what API is used to get the list...