diff --git a/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp b/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp
index a8546331..acc88255 100644
--- a/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp
+++ b/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp
@@ -92,7 +92,7 @@ CRhinoLicenseValidator::result CSampleWithLicensingValidator::VerifyLicenseKey(
license_key = L"SAMPLE-EVALUATION";
bEvaluation = true;
}
- else if (license_key.Left(8).CompareNoCase(L"EVALUATION") == 0)
+ else if (license_key.Right(10).CompareNoCase(L"EVALUATION") == 0)
{
bEvaluation = true;
}
diff --git a/rhinocommon/cs/SampleCsWithLicense/Properties/AssemblyInfo.cs b/rhinocommon/cs/SampleCsWithLicense/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..348a2d1e
--- /dev/null
+++ b/rhinocommon/cs/SampleCsWithLicense/Properties/AssemblyInfo.cs
@@ -0,0 +1,52 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Rhino.PlugIns;
+
+// Plug-in Description Attributes - all of these are optional.
+// These will show in Rhino's option dialog, in the tab Plug-ins.
+[assembly: PlugInDescription(DescriptionType.Address, "3670 Woodland Park Avenue North\r\nSeattle, WA 98103")]
+[assembly: PlugInDescription(DescriptionType.Country, "United States")]
+[assembly: PlugInDescription(DescriptionType.Email, "devsupport@mcneel.com")]
+[assembly: PlugInDescription(DescriptionType.Phone, "206-545-6877")]
+[assembly: PlugInDescription(DescriptionType.Fax, "206-545-7321")]
+[assembly: PlugInDescription(DescriptionType.Organization, "Robert McNeel & Associates")]
+[assembly: PlugInDescription(DescriptionType.UpdateUrl, "https://github.com/mcneel/rhino-developer-samples")]
+[assembly: PlugInDescription(DescriptionType.WebSite, "http://www.rhino3d.com/")]
+[assembly: PlugInDescription(DescriptionType.Icon, "SampleCsWithLicense.Resources.SampleCs.ico")]
+
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SampleCsWithLicense")]
+[assembly: AssemblyDescription("RhinoCommon Sample - SampleCsWithLicense")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Robert McNeel & Associates")]
+[assembly: AssemblyProduct("SampleCsCommands")]
+[assembly: AssemblyCopyright("Copyright © 2018, Robert McNeel & Associates")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5deff610-a9c2-4922-92bc-ff6d3deb8d5e")] // This will also be the Guid of the Rhino plug-in
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("6.0.0.0")]
+[assembly: AssemblyFileVersion("6.0.0.0")]
+
+// Make compatible with Rhino Installer Engine
+[assembly: AssemblyInformationalVersion("2")]
diff --git a/rhinocommon/cs/SampleCsWithLicense/Resources/SampleCs.ico b/rhinocommon/cs/SampleCsWithLicense/Resources/SampleCs.ico
new file mode 100644
index 00000000..3652186f
Binary files /dev/null and b/rhinocommon/cs/SampleCsWithLicense/Resources/SampleCs.ico differ
diff --git a/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicense.csproj b/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicense.csproj
new file mode 100644
index 00000000..436b174f
--- /dev/null
+++ b/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicense.csproj
@@ -0,0 +1,88 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {5DEFF610-A9C2-4922-92BC-FF6D3DEB8D5E}
+ Library
+ Properties
+ SampleCsWithLicense
+ SampleCsWithLicense
+ v4.5
+ 512
+ false
+
+
+ true
+ full
+ false
+ ..\bin\
+ DEBUG;TRACE
+ prompt
+ false
+
+
+ pdbonly
+ true
+ ..\bin\
+ TRACE
+ prompt
+ 4
+
+
+
+ C:\Program Files\Rhino 6\System\RhinoWindows.dll
+ False
+
+
+
+
+
+
+ False
+ C:\Program Files\Rhino 6\System\rhinocommon.dll
+ False
+
+
+ False
+ C:\Program Files\Rhino 6\System\Eto.dll
+ False
+
+
+ False
+ C:\Program Files\Rhino 6\System\Rhino.UI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).rhp"
+Erase "$(TargetPath)"
+
+
+ en-US
+
+
+ C:\Program Files\Rhino 6\System\Rhino.exe
+
+
+ Program
+
+
\ No newline at end of file
diff --git a/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicenseCommand.cs b/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicenseCommand.cs
new file mode 100644
index 00000000..bb726c1f
--- /dev/null
+++ b/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicenseCommand.cs
@@ -0,0 +1,16 @@
+using Rhino;
+using Rhino.Commands;
+
+namespace SampleCsWithLicense
+{
+ public class SampleCsWithLicenseCommand : Command
+ {
+ public override string EnglishName => "SampleCsWithLicense";
+
+ protected override Result RunCommand(RhinoDoc doc, RunMode mode)
+ {
+ RhinoApp.WriteLine($"{0} plug-in loaded.", SampleCsWithLicensePlugIn.Instance.Name);
+ return Result.Success;
+ }
+ }
+}
diff --git a/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicensePlugIn.cs b/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicensePlugIn.cs
new file mode 100644
index 00000000..fdffac6f
--- /dev/null
+++ b/rhinocommon/cs/SampleCsWithLicense/SampleCsWithLicensePlugIn.cs
@@ -0,0 +1,187 @@
+using System;
+using Rhino.PlugIns;
+using Rhino.UI;
+
+namespace SampleCsWithLicense
+{
+ ///
+ /// Every RhinoCommon .rhp assembly must have one and only one PlugIn-derived
+ /// class. DO NOT create instances of this class yourself. It is the
+ /// responsibility of Rhino to create an instance of this class.
+ /// To complete plug-in information, please also see all PlugInDescription
+ /// attributes in AssemblyInfo.cs (you might need to click "Project" ->
+ /// "Show All Files" to see it in the "Solution Explorer" window).
+ ///
+ public class SampleCsWithLicensePlugIn : PlugIn
+ {
+ ///
+ /// Public constructor
+ ///
+ public SampleCsWithLicensePlugIn()
+ {
+ Instance = this;
+ }
+
+ ///
+ /// Gets the only instance of the SampleCsWithLicensePlugIn plug-in.
+ ///
+ public static SampleCsWithLicensePlugIn Instance
+ {
+ get; private set;
+ }
+
+ // You can override methods here to change the plug-in behavior on
+ // loading and shut down, add options pages to the Rhino _Option command
+ // and maintain plug-in wide options in a document.
+
+ ///
+ /// OnLoad override
+ ///
+ protected override LoadReturnCode OnLoad(ref string errorMessage)
+ {
+ var rc = GetLicense(Capabilities, TextMask, OnValidateProductKey, OnLeaseChanged);
+ if (!rc)
+ return LoadReturnCode.ErrorNoDialog;
+
+ return LoadReturnCode.Success;
+ }
+
+ #region Licensing Info
+
+ ///
+ /// Returns an icon to show in the License page in Options.
+ ///
+ private static System.Drawing.Icon ProductIcon
+ {
+ get
+ {
+ var size = RhinoWindows.Forms.Dpi.ScaleInt(32);
+ return DrawingUtilities.LoadIconWithScaleDown("SampleCsWithLicense.Resources.SampleCs.ico", size);
+ }
+ }
+
+ ///
+ /// In the event that the user needs to be asked for a license, then you can
+ /// provide a text mask, which helps the user to distinguish between proper
+ /// and improper user input of your license code. Note, if you do not want
+ /// to use a text mask, then pass in a null value for this parameter.
+ ///
+ private static string TextMask => ">S\\AMP\\LE-AAAAAAAAAA";
+
+ ///
+ /// Our hard-code evaluation license key.
+ ///
+ private static string EvalLicenseKey => "SAMPLE-EVALUATION";
+
+ ///
+ /// Controls the buttons that will appear on the license notification window that
+ // is displayed if a license for the requesting product is not found. Note, the
+ // "Close" button will always be displayed.
+ ///
+ private static LicenseCapabilities Capabilities => LicenseCapabilities.CanBeEvaluated |
+ LicenseCapabilities.CanBePurchased |
+ LicenseCapabilities.CanBeSpecified;
+
+ #endregion
+
+ #region Licensing delegates
+
+ ///
+ /// Validates a product key or license.
+ ///
+ /// The license key as input by the user.
+ /// The license data extracted by validating the license key.
+ /// The results of the license validation.
+ private static ValidateResult OnValidateProductKey(string licenseKey, out LicenseData licenseData)
+ {
+ // Initialize output data
+ licenseData = new LicenseData
+ {
+ BuildType = LicenseBuildType.Release,
+ LicenseCount = 1,
+ ProductIcon = ProductIcon,
+ IsUpgradeFromPreviousVersion = false,
+ RequiresOnlineValidation = false // This sample current does not support Rhino accounts.
+ };
+
+ var evaluation = false;
+ if (string.IsNullOrEmpty(licenseKey))
+ {
+ licenseKey = EvalLicenseKey;
+ evaluation = true;
+ }
+ else if (licenseKey.IndexOf("EVALUATION", StringComparison.OrdinalIgnoreCase) > 0)
+ {
+ evaluation = true;
+ }
+
+ // Fill in the class members based on the license key and validation code.
+ // This value will never be display in any user interface.
+ // When your plugin's VerifyLicenseKey function is called, it is
+ // passed a a product, or CD, key that was entered into the Zoo
+ // administrator console. Your VerifyLicenseKey function will validate
+ // the product key and decode it into a product license. This is
+ // where you can store this license. This value will be passed
+ // to your application at runtime when it requests a license.
+ licenseData.ProductLicense = licenseKey;
+
+ // This value will display in user interface items, such as in
+ // the Zoo console and in About dialog boxes. Also, this value
+ // is used to uniquely identify this license. Thus, it is
+ // critical that this value be unique per product key, entered
+ // by the administrator. No other license of this product, as
+ // validated by this plugin, should return this value.
+ // TODO: provide an obfuscated license string here.
+ licenseData.SerialNumber = licenseKey;
+
+ // This value will display in user interface items, such as in
+ // the Zoo console and in About dialog boxes.
+ // (e.g. "Rhinoceros 6", "Rhinoceros 6 Commercial", etc.)
+ // TODO: provide a license title string here.
+ licenseData.LicenseTitle = Instance.Name;
+
+ // The Zoo supports licenses that expire. If your licensing scheme
+ // is sophisticated enough to support this, then specify the
+ // expiration date here. Note, this value must be specified in
+ // Coordinated Universal Time (UTC). If your license does not expire,
+ // then just this value to null.
+ if (evaluation)
+ {
+ var today = DateTime.UtcNow;
+ var expire = today.AddDays(90);
+ licenseData.DateToExpire = expire;
+ }
+
+ return ValidateResult.Success;
+ }
+
+ ///
+ /// Called by Rhino to signal that a lease from Rhino Accounts has changed.
+ /// If LicenseLeaseChangedEventArgs.Lease is null, then the server has signaled
+ /// that this product is no longer licensed. Your plug-in must change behavior
+ /// to behave appropriately.
+ ///
+ /// Data passed by Rhino when the lease changes
+ /// Icon to be displayed in Tools > Options > Licenses for this lease.
+ private static void OnLeaseChanged(LicenseLeaseChangedEventArgs args, out System.Drawing.Icon icon)
+ {
+ icon = ProductIcon;
+
+ // This sample does not support Rhino accounts.
+
+ if (null == args.Lease)
+ {
+ // Lease has been voided; this product should behave as if it has no
+ // license. It is up to the plug-in to determine what that looks like.
+ }
+
+ // Verify that args.Lease.ProductId is correct
+ // Verify that args.Lease.ProductEdition is correct
+ // Verify that args.Lease.ProductVersion is correct
+ // Verify thatargs.Lease.IsExpired() is false
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/rhinocommon/cs/SamplesCs.sln b/rhinocommon/cs/SamplesCs.sln
index 97b013b5..02cade24 100644
--- a/rhinocommon/cs/SamplesCs.sln
+++ b/rhinocommon/cs/SamplesCs.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2008
+VisualStudioVersion = 15.0.27130.2020
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCsCommands", "SampleCsCommands\SampleCsCommands.csproj", "{C1498326-89AB-48B0-A148-290C169CAA68}"
EndProject
@@ -63,6 +63,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCsWizardPanel", "Samp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCsDockBar", "SampleCsDockBar\SampleCsDockBar.csproj", "{9C84103D-7C1B-4685-8763-129503FEE6B6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCsWithLicense", "SampleCsWithLicense\SampleCsWithLicense.csproj", "{5DEFF610-A9C2-4922-92BC-FF6D3DEB8D5E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -177,6 +179,10 @@ Global
{9C84103D-7C1B-4685-8763-129503FEE6B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C84103D-7C1B-4685-8763-129503FEE6B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C84103D-7C1B-4685-8763-129503FEE6B6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5DEFF610-A9C2-4922-92BC-FF6D3DEB8D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5DEFF610-A9C2-4922-92BC-FF6D3DEB8D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5DEFF610-A9C2-4922-92BC-FF6D3DEB8D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5DEFF610-A9C2-4922-92BC-FF6D3DEB8D5E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE