Per-user and Per-machine Licensing
NOTE: For background information on SLPS Runtime installation which may be useful in understanding what's involved in making the SLPS ClickOnce and VSTO support work, please read http://support.inishtech.com/KB7
The default license store for SLPS needs write access to its key in the Registry under HKEY_LOCAL_MACHINE.
For normal applications, one adds a step to one’s MSI installer which, while running with elevated privileges at installation time, configures the registry in such a way as to allow the requisite actions to be performed when the application runs even when running as a normal user without elevated privileges.
In the case of ClickOnce and VSTO applications, there is no 'install step', and even FullTrust does not give one a way to elevate in any normal-user accessible manner. Another key underpinning of ClickOnce is that apps should not know about each other or be able to share data in any way. For this reason, the install directory name internally is a random GUID deep inside the user's profile, which is effectively treated as a cache by the loader - the canonical source of the application is really the .application manifest file on the source download site.
As a result of these restrictions, there is not a central place on a computer where one could store things such as licenses (even in a file) yet still allow all the users to shared a single license (or any other).
Applying a HKCU Registry redirection policy
Add a Global Customization management class
public class SlpServicesIntegration
public const string PermutationShortCode =; // TODO: please insert your permutation short code, e.g.: "c637e"
GlobalCustomizations.Instance.PermutationCustomizationsFor( PermutationShortCode ).Customize += CustomizePermutation;
public static void Initialize()
// the real work is done just once in the static initializer, but something will need to trigger its execution
static void CustomizePermutation( object sender, PermutationCustomizations.CustomizeEventArgs args )
args.Customizations.StoreLocation = StoreLocation.UserProfile;
Triggering the Integration:
- ClickOnce EXE Applications (e.g. WPF, WinForms etc.)
[STAThread] // If licensing dialog pops up [or any other WinForms file dialog], it needs to be on an STA thread or the application will hang when the user goes to select the .bin file
static void Main()
<<the rest of your mainline code>>
void ThisAddIn_Startup( object sender, System.EventArgs e )
<<any other initialization you need>>
Storage Not Configured Exceptions
If you get a store not initialized exception, it means the Triggering step (#2 above) has not been completed successfully prior to the first execution of protected code in one’s application
Running Visual Studio as Administrator and/or running with UAC off
When running Visual Studio as administrator (e.g., in order to be able to Publish Click Once apps, run against IIS etc.), the instance of the browser (e.g., Internet Explorer) that gets invoked to show the ClickOnce publish page is ALSO RUNNING WITH ELEVATED PRIVILEGES, i.e., AS ADMINISTRATOR IF VISUAL STUDIO IS. This means that clicking on the install button will behave differently (even on Vista and later versions of Windows) than starting a new [non-elevated] browser window and going to the same URL. In other words, if you want to test what your users will experience, you need to copy the URL from the browser Visual Studio shows after the publish into a manually loaded browser (i.e., to ensure that the Click Once app and/or VSTO app will NOT be elevated during the ClickOnce invocation)
Legacy Porting issues
If you receive the following exception:
System.InvalidOperationException: SLPS: FATAL ERROR: Limiting machine licenses to user due to appSetting: Slps.RedirectMachineToUser is no longer supported. Please refer to http://support.inishtech.com/KB11 for details regarding suitable migration and workaround approaches.
this indicates that you should:
- Remove the Slps.RedirectMachineToUser appSetting from one’s app.config
- Employ the simplified approach detailed in this article to have the runtime apply the same policy as implemented via the previous guidance