I have an application that is installed per-machine (since it uses a service). One part of the application is a system tray application that allows the logged-in user to monitor the service operations. I'm trying to figure out how to best install this monitor application.
Each individual user should be allowed to configure whether or not he/she wants to run the monitor application at login. This means that the HKLM/Software/Microsoft/Windows/Run key is out - this only allows configuration for all users.
There is of course the corresponding HKCU-key, however if one simply installs to this key, it will only be for the user that installs the application.
The SO question Launch app on startup for all users, but also allow per-user setting (Windows) refers to the technique of simply having a user-configurable regkey or similar that is checked by the startup-application on to determine whether or not to run. But this means that the application has to start in order to check the value and I would prefer not to bloat the user's startup if I can avoid it. The benefit of this approach is that it is possible to remove the regkey on uninstall.
Another way to accomplish the installation part may be to use Active Setup to create the HKCU regkey on login, this is however undocumented and it seems to me that there is no easy way to uninstall the regkey if the application is uninstalled? I would assume that leaving registry values under the Run key for HKCU might create problems for users after uninstallation.
Is there a standard way to handle per-user startup applications using Windows Installer? Especially with regard to how to uninstall these later on?
Looks to me like you're close to answering your own question. I think you may just need to divide up the responsibility of configures whether to auto-run for each user... er, let me explain:
You can use either a self-healing component of HKCU Registry keys or ActiveSetup to ensure that every user gets the configuration.
If you use an HKCU Registry key, your MSI installer needs to have a component with it's "key file" as an HKCU entry--so thus the first time a new user launches the program, Windows Installer will do a self-heal to write those entries. One of those entries would be your HKCU/Software/Microsoft/Windows/Run value, but not the key value, because you want the users to be able to remove it and not have it come back every time they run the program! You would then want your program to have an option to remove the auto-run value.
If you use ActiveSetup (which I would recommend because it's simple and it "just works"), then you might find it easiest to make a simple app (or VBScript or such) which prompts the user if they want to have the monitor program auto-run. So your ActiveSetup would launch the prompt program/script, and the prompt program would create the HKCU/Software/Microsoft/Windows/Run value or, better yet, just a shortcut in the user's Start Menu\Programs\Startup directory.
A bit lowtech possibly, but can't you just add a shortcut to the user's startup folder (Start menu/Programs/Startup)?
I guess you would use the HKLM/Software/Microsoft/Windows/Run in this case. The feature to run the monitor application at startup or not really belongs to the monitor application and not the installer. At log-on the monitor application can detect if this is the first time that the monitor application has been run and present the user with an option to always run the monitor application on start up or not.
Related
Recently, I once again came across the problem of having to run my Windows app on startup and wondered which of the options is the most usual one and causing least trouble long term.
Registry
Add string value of the path to your exe to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run or \HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run for x86 applications running on a x64 Windows.
Feels the most natural
Fairly easy, especially when using frameworks simplifying registry entry creation
When uninstalling an application, you could end up with a dead registry entry
User won't be able to edit this entry
Autostart
Create a .lnk inside the user or system wide autostart folder (shell:startup).
Able to do it programmatically
Very easy to create, add arguments and modify
User is able to edit entries in his usual environment
Task scheduler
Create a 'When the computer starts' or 'When I log on' run entry in the Task Scheduler.
Able to do it programmatically
There is a GUI, but I would assume the average user won't find it
So what are further considerations when selecting an option?
Registry is always being used by production software, since that's the most controlled way and Windows suggests it.
Pros:
No need to enter the users personal space (powershell:startup)
Option to autostart the software only once (windows cleans up the registry)
Decide if the software should autostart for the whole local machine or the current user
Can be executed even when the machine is started in safe mode by using RunOnce with an exclamation point (!)
Here you can read more information about using Run and RunOnce Registry Keys.
shell:startup(not recommended) is the personal startup folder of the user, where shortcuts are being stored, that have been created & copied over by the user. The user will also experience an error prompt, if the application has been deleted, but the shortcut still remains. [BAD USER EXPERIENCE]
Task Sheduler is great for scripting, conditional event triggering and mostly used by Administrators. This option would be overkill, since Registry is much simpler and doesn't leave a Task Event, that the user has to disable on his own.
There is a GUI, but I would assume the average user won't find it
Task Manager [Startup tab] will display applications that will be automatically executed by Windows (registry & startup), which allows the user to enable/disable the software from doing that, so that's not an issue.
TLDR: Registry is by far the most used and best option to automatically run software.
The registry and start-menu are pretty similar. The registry gives you zero control over the execution, the only setting is the command line arguments. The start-menu uses shortcuts so that gives you the ability to control the working directory and initial window state.
The task scheduler is not the traditional way to launch startup applications. It feels like overkill and that you are trying to be obscure on purpose.
I'm building an installer with WiX to install a program, per machine (not per user), and it gives them the option to register the program. Registration involves entering user name and organization (or accepting some defaults from Windows settings), and entering a valid registration key. When the registration key is validated, I write registry settings in the HKEY_LOCAL_MACHINE area with this information. Under Windows, when one runs the MSI, it prompts automatically for an admin password to be able to set registry values in HKEY_LOCAL_MACHINE. So far life is good...
I am including an option in the MSI to give the user the option to defer registration until a later point in time. However, if the user is a normal user and they are running the application, if I have a dialog in the app which prompts for name/org/product-key, Windows doesn't the app to write the information to HKEY_LOCAL_MACHINE. So a user cannot use the application itself, running as a normal user, to perform a registration per-machine as the MSI does after prompting for admin credentials.
My thought then was, for post-installation registration, to either (a) find a way from within the application to elevate privileges, with a prompt for admin credentials, allowing it to write HEKY_LOCAL_MACHINE (is this possible?), (b) include an option in the installer that, when run and the app is already installed and not registered, walks through the registration as it would during a normal install. It would then prompt for the admin credentials and life is good again. Alternatively, (c) create a separate MSI that just does registration, install this with the program, and call this MSI from the program when the user selects the "Register..." command in the program.
I've not seen either of these approaches done by any applications before, so I'm not sure either is a good approach. Other than that, however, I'm not sure how, post-installation, I can conveniently allow the user to do a per-machine app registration. Ideally, I'd like to be able to do it from a command within the app, but re-running the installation MSI would be minimally acceptable.
How is this normally done? Or are per-machine installations even normally accompanied by per-machine registrations?
Very good question - I have dealt with this issue many times myself. No ideal solutions, but several options (as you have already discovered).
Before answering, I want to point out that I have a strong aversion against doing too much registration and configuration in the setup itself. It is error prone, and much better done in the application itself for a plethora of reasons: Installer with Online Registration for Windows Application (recommended quick read - tidbits from real life experience).
Writing to HKCU
As you already know, one option is to keep the license key and registration in HKCU only. This is often acceptable unless you want to share a license key between many users on the box. The license key, if added to HKCU, will also generally roam with the user to other computers - which can be helpful or desirable.
Personally, this is the option I prefer: not registering anything in the setup, but writing to HKCU or the user-profile from the application (as explained in the link above as well). As stated, the only drawback is that you can't write a shared license key to HKLM so it applies to all users and not just a single user. This appears to be the core of the problem you are describing.
Writing to HKLM
Setup writes HKLM: Write the HKLM license key (and registration) during the setup to HKLM as Phil has described above using the default Windows Installer properties (just listing this as an option - which you already know about). This should work OK in my opinion - but your issue seemed to be to allow the "deferred registration".
Custom HKLM ACL permissioning: In order to write to HKLM from your non-elevated application, one way to do it is to use your setup to apply custom ACL permissions to the location in HKLM where you want to write the shared registry key from your application. Your application can then freely update this specific location in HKLM at any time without elevated rights. You simply add ACL write access for "Users".
WiX supports this, but I don't have a sample for you available, please check the WiX documentation for permissioning.
Using custom permissioning is generally frowned upon (and I agree it is not ideal design), but it allows any user to add a license key to HKLM without any elevation after the install (and also allows any users to delete it - which can be a problem).
See section 14 here for a quick description of why custom permissioning is not generally recommended: How do I avoid common design flaws in my WiX / MSI deployment solution?
In summary, I don't generally suggest setting custom permissions, but it will definitely work. I have done it myself when client requirements are such that this is the only thing they will accept. It will violate logo requirements for Windows applications, but it should be less serious than the security issues that result from option 3 below.
Run app as admin: If you don't want to apply ACL permissions, I believe you can prompt the user for admin rights for your application as described here (I believe this is what Phil referred to in his comment if I understand correctly):
How do I force my .NET application to run as administrator? (the legendary Hans Passant - one more answer).
This is most definitely not recommended (but we want to show people what is possible too). Your whole application will run with admin rights all the time, which is not a good idea at all.
Doing this will violate a key part of logo requirements for Windows applications and you will also open your application up to attack from malware.
Definitely try to make your users understand the consequences of this "easy fix". I would make sure to put all responsibility on the client if they go for this option - they must understand what they are doing.
Note that you should be able to use this manifest approach to launch a separate EXE with elevated rights to do only the registration. See next bullet point.
Elevate app on demand: I am not familiar with the technical details of elevating your application on demand whilst it is running - as you invoke a dialog or feature that needs HKLM access. Perhaps Phil knows a way to achieve this? I found some links though:
Elevating during runtime (from Code Project)
How to elevate privileges only when required? (good read)
Skimming the linked content above, it seems like you can launch a separate EXE with elevated rights to do your registration - a known option for you I assume.
Would love to hear back if this is something you decide to try. Could be useful for all of us.
Internet validation: Just throwing an option out there: what I often want to do is to put the whole registration license key validation online from within the application (never, ever try this from the setup, just so that is mentioned - a setup that tries to access the Internet might be the biggest deployment anti-pattern of all - at least for now).
I write the license key from the setup, and the validation of it takes place on application launch against a server on the Internet. Then there is no validation code in your application or your setup to crack.
You need an Internet "handshake" and you can repeat this process per user - allowing you to tightly control who is using your license key.
Nothing is ever easy, and proxy server issues could cause problems. Corporate deployment would also mean that such "online activation" is frowned upon. They want applications fully installed after deployment.
Separate registration MSI: I would prefer not to create a separate MSI just for the registration process as you mention in your question. This just seems like unnecessary complexity that can break easily. For one thing you get a dual source problem that must be permanently maintained. I would guess that this could become a classic support issue.
Re-run original MSI: I am honestly not sure if re-running your original setup to do the registration will launch it elevated or not. I think it will be elevated (should be, can't see any reason why it shouldn't - the MSI database stores a flag to determine if elevation is required "Word Count"), and then you should be able to add your registration details provided you access the registration dialog from the setups "modify" or "repair" modes.
This kind of registration is usually done using the standard Windows Installer properties so it just works.
If you have a verification key then it's typically associated (in the dialog) with the standard PIDKEY property which then after validation becomes the ProductId property.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370826(v=vs.85).aspx
Similarly the user name and company name are associated in the dialog with the USERNAME and COMPANYNAME properties.
After this, they're available through (Win32) MsiGetProductInfo () by asking for RegOwner etc:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370130(v=vs.85).aspx
or similar APIs (WMI does some of this).
So generally speaking you just set the properties from the dialogs and it all just works with no need for you to write them to the registry.
I was going to ask this in superuser but it is related to C/C++ and Win32 programming so I'll ask it here. I'm looking to add a step between user login and the Windows shell for Windows 7+. These are the things I've researched and tried with limited success:
MSGINA Stub, which seems like it would work perfectly but was discontinued as of Windows Vista so I can't use this.
I've looked at custom Windows Credential Providers but I'm not entirely sure this will do what I want (launch an application after login and before the windows shell).
A (semi) custom shell which would do what I need then launch the normal Windows shell (explorer.exe).
Option 3 has gotten me the closest but my problem is that I can't start explorer.exe as a shell if I've created the HKLM\...\Winlogon:Shell registry value pointing to my program. I could create the Shell value in HKCU then change it to explorer.exe before quitting and launching explorer then restoring the value to my program. This would work but is not as secure as using HKLM. In this case, I can't even use HKLM as my program is being executed in the current user's context and the user does not have write permissions to that key.
Are there any creative ways that I can do this or any other possibilities that I'm missing? Option 2 above didn't seem to be viable but please correct me if I'm wrong.
I like RbMm's answer, but for completeness, another option is a Credential Manager.
(Note: a Credential Manager is not the same thing as a Credential Provider.)
Using a Credential Manager might be preferable to using userinit in any of the following scenarios:
You want to run code with elevated privileges.
Your code needs to run at a very early stage in logon, e.g., before roaming profiles are loaded.
You need the user's password.
Some reasons you might not want to use a Credential Manager:
It runs as a DLL inside winlogon so you need to be particularly careful that your code is correct.
Depending on what you're doing, it might be too early in the logon sequence. :-)
It doesn't run in the user's context. (There is a way around this, but it's pretty hacky.)
I think that best way for insert a program between login and explorer shell in Windows is register own application under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon : Userinit
default userinit.exe run exactly between login and shell and can be customized:
For example, to have a program run before the Windows Explorer user
interface starts, substitute the name of that program for Userinit.exe
in the value of this entry, then include instructions in that program
to start Userinit.exe.
Many Windows programs are able to run an update when they start, without an admin prompt. Similarly, my program needs to update itself, without any user input. Any user who logs in needs to be able to use the program.
My program can already find new updates, download them, and run them, but the NSIS installer/updater requires admin rights.
What would I need to do to implement this using Free Pascal and NSIS, short of giving all users access to the installation directory?
Is your application that important that you need to do this? How often do you actually plan to push out updates?
Most applications can probably get away with just elevating with UAC each time it needs to install a update.
If you absolutely feel that you need to "bypass UAC" then you can do what Firefox does; install a NT Service. You don't start this service in the installer but you must call GetNamedSecurityInfo+SetNamedSecurityInfo so you can add SERVICE_START access for the Everyone group to the ACL. Your application running as a normal user can then start this service when there is an update and the service does the updating.
From a security standpoint there are some dangers here because the service runs with full access to the system so you must make sure that your updates are signed so it does not become an easy to use backdoor if someone is able to pull off a man in the middle attack.
I personally think that you should consider doing per-user installations if your program is not too big...
I'm working on an installer for our application. The installer makes some changes to the HKEY_CURRENT_USER\Software\Company\AppName registry key, which the application then looks for the first time it runs. The application then does different things based on the registry keys it finds.
This works great, until you try to install the application as a user account (i.e. non-administrator) on windows 7 (and maybe Vista, I haven't tested that yet).
When the user tries to install the application, Windows elevates to the administrator account's credentials. This means that any changes to HKCU in the registry are made to the administrator's registry, not the launching user's registry. Thus, the keys are not visible to the application when it launches for the first time under the user's account.
We can't be the only people whose installer needs to communicate with the app it installs. Is there no way to reliably use the registry to do this?
We can't rely on the user launching the app after he installs it, so passing the information as a command-line parameter isn't a viable solution. The only way I can see to do it is to have the installer invoke a utility as the original user, which gets or sets the registry key itself; this seems to be a bit of a silly hoop to have to jump through.
Edit: The application needs to delete the keys after it's used them, so I can't just put them in HKEY_LOCAL_MACHINE.
There are 2 recommended approaches for what you want:
Use a per-user installation which
doesn't require Administrator
privileges. You will be able to use
HKEY_CURRENT_USER, but your product
is not installed for all users.
Use a per-machine installation which requires Administrator privileges. In this case you need to redesign your application so it reads its settings from a configuration file. HKEY_CURRENT_USER should be used only when saving user-specific settings, not for global application settings.
Basically, if your application is per-machine, it should use HKEY_LOCAL_MACHINE or a configuration file. If it's per-user, you can use HKEY_CURRENT_USER. Any other combination has limitations and will not work the way you need.
If you need your application's information to be available to all users, use the HKEY_LOCAL_MACHINE hive.
EDIT - 2 alternatives:
Change the security of your registry
keys to allow users to edit/delete
them,
Use the ProgramData directory (instead of the registry) to store
the data.