This article offers guidance on how to ensure the older Microsoft.Licensing Runtime components are installed correctly before execution of any protected code. In order to offer a consistent and clear experience to end users, the Runtime will now - prior to the first attempt to execute protected code - consistently throw an exception up front if it is invoked without having been installed and configured correctly.
Runtime Installation
In order to offer a consistent and clear experience to users, the Runtime will - prior to the first attempt to execute protected code - consistently throw an exception if it is invoked without having been installed and configured correctly.
The aim of this new approach is to provide a consistent behaviour across all platforms that will minimize the testing and troubleshooting effort required of you the ISV.
Therefore the recommended approach to installation of the Microsoft.Licensing runtime components is -
- As part of the installation of the application, have your installer invoke a .NET Installer class based on the Installer class included in the runtime . As is normal for an installer, this portion needs to run elevated, (i.e., as Administrator on Windows Server 2003, XP or with UAC off / elevated on a systems with UAC).
- At the start of the application's Main(), add a check that the installation has been carried out properly which displays an appropriate diagnostic message (for example License Administrator utility does this when it is run on a machine without having been installed). This check does not require admin privilege or elevation.
While this might appear to make deployment more complex, this approach does mean that the only point at which a Software Potential protected application requires Admin user rights is during the first installation. This approach is in accordance with Windows Logo requirements for Vista and later Operating Systems.
Implementation Steps
The following are the steps to ensure the Runtime components are correctly installed during application installation, avoiding downstream errors at application runtime:
- Add a reference to the Microsoft.Licensing Runtime DLL belonging to your permutation to your application project.
- Add an installer class to your app:
using System.ComponentModel; using Slps.Licensing.Installation; namespace Slps.VendorTools.MinimalProtectedApp { [RunInstaller(true)] public class Installer : PermutationInstallerBase { public Installer() : base( "123XX") // TODO substitute in your permutation short code { } } }
- Add an installation check to your Main():
using System; using Microsoft.Licensing; namespace Slps.VendorTools.MinimalProtectedApp { class Program { [STAThread] static void Main(string [] args) { try { if (VerifyInstalled()) Execute(); } catch (Exception exception) { MessageBox.Show(exception.ToString(), "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); } } static bool VerifyInstalled() { try { using ( var installer = new Installer( ) ) installer.VerifyInstalled(); return true; } catch (StorageInaccessibleException ex) { MessageBox.Show(ex.Message, "Licensing installation issue", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } } static void Execute() { // Invoke The rest of your app } } }
- Add a call to the .NET Managed Installer class from your installer:
- Visual Studio Deployment Projects (.vdproj projects) have a Custom Action option - simply tell it to run the Installer during the "Install" phase. Add "Primary Output from YourApp.exe" to the "Install" step, and set the InstallerClass property to True.
- InstallShield 2009 (and probably earlier versions) have a simple flag for this - you simply indicate that your app's managed installer is to be invoked by ticking a checkbox. Competing products have equivalent features.
- WiX has a custom action called ManagedInstall in InstallUtilLib. For some more info, see Install Runtime Using Wix.
- InnoSetup doesnt have any direct .NET support. This means the simplest solution is to use installutil on Slps.Runtime.Installer.dll from your installer as outlined in the next section below.
Setup Using Wix Installer
When adding a Custom Action in the <product>.wxs file ensure:
a) Add the Execution=’deferred’ property to ensure deferred execution of the install custom action
b) Add the Impersonate=’no’ to ensure that the action runs with the correct admin privilges
c) Ensure that the custom action occurs before the "InstallFinalize" step using the <InstallExecutionSequence> element.
The following code snippet illustrates a CustomAction for an application "ConsoleWixApp.exe"
<CustomAction Id="ManagedInstall" Execute='deferred' Impersonate='no'
Directory='INSTALLFOLDER'
ExeCommand='"[WindowsFolder]Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe" /LogToConsole=false "ConsoleAppWix.exe"'
Return='asyncNoWait'>
</CustomAction>
<InstallExecuteSequence>
<Custom Action='ManagedInstall' Before="InstallFinalize" />
</InstallExecuteSequence>
Setup without Installer using XCopy Deploy
If you're just trying to do a quick "xcopy deploy" for test purposes, you could use one of the following approaches. Note each of these needs to run elevated, i.e., you need to start a command prompt with “run as Administrator” to run the commands successfully.
A) Use Slps.Runtime.Configuration.exe
- Copy Slps.Runtime.Configuration.exe and its dependencies:-
- Slps.Runtime.Configuration.exe
- Slps.Runtime.Installer.dll
- Microsoft.Licensing.Utils2.0.DLL
- Microsoft.Licensing.Runtime2.0.DLL
- Microsoft.Licensing.Permutation2.0.dll or, as of 3.0.1910 release of Code Protector, your custom Microsoft.Licensing.Permutation_123XX_2.0.dll.
- Run:
Slps.Runtime.Configuration /Install from an elevated command prompt.
B) Use installutil on Slps.Runtime.Installer.dll
- Copy Slps.Runtime.Installer.dll and its dependencies:-
- Slps.Runtime.Installer.dll
- Microsoft.Licensing.Utils2.0.DLL
- Microsoft.Licensing.Runtime2.0.DLL
- Microsoft.Licensing.Permutation2.0.dll or, as of 3.0.1910 release of Code Protector, your custom Microsoft.Licensing.Permutation_123XX_2.0.dll.
- Run:
%windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe Slps.Runtime.Installer.dll
Please note that the approaches A and B above are not intended for end-user usage - they're advanced tools intended for people developing custom licensing and/or installation schemes.
C) Use InstallUtil on your EXE/DLL containing your Managed Installer
- Add an installer to your software as covered in steps 1 and 2 of Implementation steps.
- Run:
%windir%\Microsoft.NET\Framework\v4.0.30319\installutil.exe <your assembly containing the Installer class>.<dll/exe>
D) Add a self-installation command line option to your EXE
- Prior to your VerifyInstalled() step in your EXE, add processing for commandline arguments that executes the Installer if requested:
[STAThread] static void Main() { try { var singleArgument = args.Length == 1 ? args[0] : string.Empty; if (singleArgument.Equals("-install", StringComparison.OrdinalIgnoreCase) ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location }); else if (singleArgument.Equals("-uninstall", StringComparison.OrdinalIgnoreCase)) ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location }); else if (VerifyInstalled()) Execute(); } catch (Exception exception) { MessageBox.Show(exception.ToString(), "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
- Run <your assembly containing the Installer class>. exe -install either interactively or via your installation script. Again, elevation is required as usual in order to run the installation portion (but your application should run normally unelevated).
Error Messages associated with incorrect installation
You may see one of the following error messages if the Microsoft.Licensing Runtime components are not correctly installed.
Slps.Licensing.StorageNotConfiguredException: Licensing storage is not configured. Please ensure software has been installed correctly.
This is thrown from PermutationInstallerBase.VerifyInstalled() (normally you’ll have an Installer class derived from this) if the installation has not been completed when the installation check in your protected application’s Main is triggered by the user starting the application. Typically the code block in the application involved is as follows:
static bool VerifyInstalled()
{
try
{
using ( var installer = new Installer( ) )
installer.VerifyInstalled();
return true;
}
catch (StorageInaccessibleException ex)
{
MessageBox.Show(ex.Message, "Licensing installation issue", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
The above code
- Lets the exception get thrown if there’s a problem.
- Reports the problem to the user.
- Returns false if there is a problem, so that the calling code can abort the running of the application – at this point the user needs to reinstall or otherwise remedy the fact that installation has not completed successfully.
Microsoft.Licensing.StorageInaccessibleException: Licensing storage is inaccessible. The license store has insufficient permissions. An Installer needs to have successfully completed (with Administrator privileges) in order to execute protected code.
This is thrown from the Runtime when an application is trying to execute protected code and indicates that there is a problem accessing the registry store. The likely cause is that registry permissions have not been assigned correctly (e.g., the key may exist, but as the installation has not completed correctly, the registry cannot be accessed in the current context. In this case, the remedy is to ensure that installation has successfully completed prior to the first attempt to execute protected code via a VerifyInstalled() method as detailed earlier in this document.
Storage not configured correctly at time of session opening - has storage been configured? Not throwing Slps.Licensing.StorageNotConfiguredException (this is acceptable if one is only calling ConfigurePermissions).
The above message gets written into the log whenever there is an attempt to execute protected code without there being a license store in place. Typically the only reason for this to arise is that one is running the Install step (i.e., you will always see this during the install step the very first time an SLP-protected application is being installed). If you see this entry in the SLP Log at any other time (e.g., during normal running of the application), this indicates that installation has not been installed correctly. As in the other cases, the best remedy for this condition is to add a VerifyInstalled method to your application’s Main().
Microsoft.Licensing.Utils.GenException: Failed to set registry parameter [_tmpbalikeda63] to value System.Byte[] ---> Microsoft.Licensing.Utils.GenException: SLPS not installed correctly, please ensure the root node has been created and the permissions have been applied correctly
at Microsoft.Licensing.Utils.RegistryUtil.VerifyInstallation().
(in later versions: at Slps.Common.Internal.Registry.GlobalRegistryRootManager.VerifyInstalled(()
May include InnerException: Microsoft.Licensing.Utils.GenException: SLPS not installed correctly, please ensure the root node has been created and the permissions have been applied correctly.
As with the other exceptions, this is a symptom of installation not having completed successfully prior to an attempt to run protected code. The remedy, as in the other cases, is to add a VerifyInstalled() method call to your application’s Main().
Comments
0 comments
Article is closed for comments.