R11 License Server & SNHookClass

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 16/04/2009 at 14:37, xxxxxxxx wrote:

Serial / License Key format:
For the purpose of example, let's look at the "Hair" module (plugin) string...

    
    
      
      **Mod: Hair :**                            [11-0-1017643]      <<40300012345-AAAA-BBBB-CCCC-DDDD>>  
    

...the first part (in bold/underlined) is just a textual name for the plugin - this gets displayed in the License Server interface, but the exact name is not crucial (it doesn't necessarily need to "match" anything else in the system - it's only used for display purposes).

    
    
      
      Mod: Hair :                           **[11-0-1017643]**       <<40300012345-AAAA-BBBB-CCCC-DDDD>>  
    

...the next part (enclosed in square brackets) is important.  The '11' is the C4D version, the '0' is the platform (Mac or PC, but generally no longer used - I think this can always be '0') and finally, the PluginID of the plugin being registered (ie. you need to insert your plugin's ID here).

    
    
      
      Mod: Hair :                           [11-0-1017643]      << **40300012345-** AAAA-BBBB-CCCC-DDDD>>  
    

...the final section (enclosed in double angle brackets) is the actual serial number / license key for the plugin.
> Of special note here is that the underlined digits (last 5 digits of the 11-digit serial number) need to match the last 5 digits of the CINEMA 4D serial number - this tells the License Server which "serial package" this plugin belongs in.
...the first 6 digits/characters of the 11-character  string before the dash are not important/used by the License Server, but those last 5 digits need to match.

    
    
      
      Mod: Hair :                           [11-0-1017643]      <<40300012345 **-AAAA-BBBB-CCCC-DDDD** >>  
    

...everything after the dash is where your plugin's license key goes (however you go about generating that).
So to recap:
Plugin name [11-0-yourpluginIDdigits] <<xxxxxx12345-yourlicensekeygoeshere>>
...using the above information and my Riptide Pro plugin as an example, here is a sample license key string that can be pasted into the License Server...
Riptide Pro [11-0-1022532] <<RipPro12345-XOXOXOXOXOXOXOXO>>
...where the '12345' would be replaced by that user's last 5 digits of his 11-digit serial number and the XOXO partwould be replaced by a 16 character generated license key that my plugin uses.
(continued in next post...)

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 16/04/2009 at 15:06, xxxxxxxx wrote:

Multi-License:
Before getting to the implementation, let's take a look at that last string (from the first post)...

    
    
      
    Multi-License R11  (001) :               [11-0-200000174]    <<201001 **12345** -AAAA-BBBB-CCCC-DDDD>>  
    

...this is the "Multi-License" serial number that your customers will recieve from Maxon when they purchase a multiple license package.  As you can see from the underlined (and fictional) '12345' last 5 digits of the serial number, it is tied to a specific Cinema 4D "serial package" and is the mechanism that tells the License Server how many seats can be served for that serial package.

    
    
      
    Multi-License R11  (001) :               [11-0-200000174]    <<201 **001** 12345-AAAA-BBBB-CCCC-DDDD>>  
    

...the "seat count" is contained in the 4th, 5th and 6th digits of the number, above (from 1 -> 999 seats).  In this case, it's just a "single seat" multi-seat license :).
> NOTE: The 'seat count' is the total number of seats sold as that multi-license package.

    
    
      
    Multi-License R11  (001) :               [11-0-200000174]    << **20100112345** -AAAA-BBBB-CCCC-DDDD>>  
    

...in the implementation section later on, note that this is the 11-digit  string that GeGetSerialInfo() will return as the serial number.
If we combine information from the above two points, the result is:

  • For use in a License Server environment, the plugin needs to have it's key generated based on the "Multi-License" number instead of the (normal) "CINEMA 4D" number.
  • Since the "seat count" will always be reported as the total number of seats in that package (ie. not the number currently in use), you will need to sell your plugin "multi license" packages to match the seat count of the ones the customer has (ie. pricing is up to you, but you can't really sell someone a "25 seat" license and expect to limit usage to that, within a "100 seat" Cinema' package).

...in the next post, I'll start to pull some of this together and get into a working implementation using the SNHookClass...

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 16/04/2009 at 15:41, xxxxxxxx wrote:

Implementation:
Given the background information above, the first thing to note is that the license-key for the plugin needs to be different in a License Server environment than we normally use for stand-alone usage - it now needs to have 11 additional characters and a dash tacked on the front (technically, the dash may not be required, but can be used for our own parsing).  The last 5 of those characters also needs to match the last 5 digits of the "CINEMA 4D" (and "Multi-License") 11-digit numbers.
Again, just to recap and using Riptide Pro as an example, my normal license keys consist of 16 alpha-numeric characters, with no dashes or spaces or any other special characters, so I'll represent that as:
XOXOXOXOXOXOXOXO
...This is what I send to customers once they purchase the plugin for entering into the "Personalize" dialog.
For use in a License Server environment, I need to send my customers a longer formatted string:
Riptide Pro [11-0-1022532] <<RipPro12345-XOXOXOXOXOXOXOXO>>
...this lets them copy/paste it into the License Server's "Add Serials" dialog and tells the License server the plugin ID and which "serial package" it belongs with.  The XOXO part of the above string in this case (my plugin's generated license key) would be based on the 11-digit serial of the "Multi-License" serial number, instead of the "CINEMA 4D" serial numbers.
So now we can get into some implementation details...
SNHookClass::SNCheck() :
I don't plan to list a complete SNHookClass implementation here, but the primary routine/mechanism within that class used to validate license keys is the SNCheck() call...

    
    
    SNCheck(const String& c4dsn, const String& sn, LONG regdate, LONG curdate)

...this routine is called by the system at startup and allows your code to validate the license key that the user entered - again, how this key is generated and validated is up to the developer - but the example code to follow will cover some details related to License Server usage.
Before we get to the code, are a few specific points about SNCheck() being called within a License Server environment:

  • c4dsn - this will (should) be the same as you always see - it's the 11-digit string from the stand-alone CINEMA 4D serial number.
  • sn - this string (your plugin's license key) will have those extra 11 characters and dash tacked on the front.
  • regdate - is INVALID/meaningless - you can not use it to check for trial period expirations.

...to get the 'Multi-License' digits, we need to call the GeGetSerialInfo() routine and if the 'nr' String member of the filled-in SerialInfo structure has Content(), then that's the Multi-License digits.  If there is no Content(), then C4D is being run in stand-alone mode (ie. not being fed keys from a License Server).
The next post will include the actual sample code (with additional comments) for a SNCheck() routine...

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 16/04/2009 at 16:03, xxxxxxxx wrote:

The Code:
Below is sample code for a "License Server aware" SNCheck() routine, that can be built with the R10.1 SDK and taking all of the above into account. Obviously some sensitive details are left out...
-------------------- S N I P ------------------------

    
    
      
    // - SNHookClass.SNCheck  
    //*---------------------------------------------------------------------------*  
    LONG SNCheck(const String& c4dsn, const String& sn, LONG regdate, LONG curdate)  
    //*---------------------------------------------------------------------------*  
    {  
        if( !regdate && !sn.Content() )  
            return SN_WRONGNUMBER;
    
    
    
    
        bool bCalledByServer = false;  
        LONG licCount = 1; // initialize a "license count" (if you need/care to know that)
    
    
    
    
        // set up some new strings (that can be altered)  
        String c4d_sn = c4dsn; // initialize the C4D serial number to the one passed in  
        String plug_sn = sn; // initialize the plugin license key to the one passed in
    
    
    
    
        // only need to check for multi-license if this is R11 or later...  
        if( GetC4DVersion() >= 1100 )  
        {  
    #ifndef SERIAL_MULTILICENSE  
    #define SERIAL_MULTILICENSE 2 // this #define lets us build with the R10.1 SDK  
    #endif  
            SerialInfo si;  
            GeGetSerialInfo(SERIAL_MULTILICENSE, &si);
    
    
    
    
            // See if this is a multi-license-server based installation  
            if(si.nr.Content())  
            {  
                // if you need to find the license count, you can do it like so...  
                LONG licCount = si.nr.SubStr(3,3).StringToLong(NULL);  
                // GePrint("Using multilicense for " + FormatNumber(licCount, FORMAT_LONG, 0) + " seats"); 
    
    
    
    
                //--------------------------------------------------------------------------------  
                // since this is a multi-license based config, we'll switch over to use the serial  
                // number from GeGetSerialInfo() instead of the one passed into this routine (the  
                // one passed in is the original 'stand-alone, single seat' version, that doesn't  
                // have the seat count info embedded).  
                //--------------------------------------------------------------------------------  
                c4d_sn = si.nr;
    
    
    
    
                //--------------------------------------------------------------------------------  
                // Note that we also need to skip over the extra data added to the front of the  
                // plugin's license key (11 digits/characters and a dash)...  
                //--------------------------------------------------------------------------------  
                LONG dashPos;  
                if(sn.FindFirst("-", &dashPos,0))  
                {  
                    plug_sn = sn.SubStr(dashPos+1, sn.GetLength()-dashPos-1);  
                }
    
    
    
    
                //--------------------------------------------------------------------------------  
                // At this point, we have switched over to using the multi-license serial number  
                // and patched up our plugin's license key to match. Assuming these are the  
                // strings you used to generate your plugin's license key to begin with (however  
                // you go about doing that), you should be good to go - the rest of your code  
                // after this point may not even need to know if this is a single or multi-license  
                // configuration, but you can always set up a boolean or check for "20" as the  
                // first 2 characters of the c4d_sn string if you need to later.  
                //  
                // In this case (at least for some code below here), I'll set a boolean...  
                //--------------------------------------------------------------------------------  
                bCalledByServer = true;  
            }  
        }
    
    
    
    
        // Demo/Beta modes  
        if (plug_sn.GetLength() == 4L)  
        {  
            //----------------------------------------------------------------------------------  
            //**********************************************************************************  
            // NOTE: When called from within a License-Server environment, 'regdate' is INVALID  
            // (it appears to be uninitialized/garbage value), so there's no way to use  
            // that variable for DEMO-expiration tests.  
            //  
            // There are some other issues related to actually allowing timed trial periods  
            // within a License-Server environment, but if you decide to allow it, your plugin  
            // will need to track the regdate by some other means.  
            //**********************************************************************************  
            //----------------------------------------------------------------------------------  
            if( bCalledByServer )  
                return SN_WRONGNUMBER;
    
    
    
    
            LONG numDays = 0L;
    
    
    
    
            if (!plug_sn.Compare("DEMO"))  
                numDays = 30L;  
            else  
                return SN_WRONGNUMBER;
    
    
    
    
            // etc...... continue whatever 'DEMO' mode parsing as needed below here and then\n    
            // (if not DEMO mode), call your license key validation routine, etc.  
    
    
            // ............etc.  
        } 
    
    
    
    
        // ........snip...... //  
    
    
    
        return SN_WRONGNUMBER;  
    }  
    

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 16/04/2009 at 16:07, xxxxxxxx wrote:

... I hope the above is usefull - it's just based on my current understanding and from the resulting implementation to get my plugin working correctly.
Many thanks go out to Rick Barrett and Kai Pedersen for providing the necessary info to get this working.
If you have questions or corrections, please post them.
Cheers.
Keith

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 16/04/2009 at 16:40, xxxxxxxx wrote:

Here's a few other tid-bits of clarification:
Q: If the user has set his machine up to use the License Server, can't the plugin license keys just come from the local machine?
A: Nope - not as currently implemented, at least.  They ALL come from the server.
Q: So could the user just 'register' a single-seat license with the License Server and have the server combine that dynamically with a seat from one of the "serial packages"?
A: Nope - the License Server doesn't do any "serial package combining" - it can serve 'less' than a full list of licenses to some machine (if the user only has "XL" installed and there are no "XL" package seats left, they might end up getting a partial "Studio" package), but the License Server can't/doesn't pull in licenses from other serial packages to combine into a larger package.
Q: So, that means that each license key for my plugin is directly tied to exactly one "serial package" - right?
A: Yup.  And therefore, the "seat count" that you sell them should match the seat count of that package.  And those last 5 digits of the 11-digit serial string tacked on the front of your license key must match the same 5 digits of that serial package.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 17/04/2009 at 09:18, xxxxxxxx wrote:

BTW,  there are basically two different ways to implement license key validation in Cinema 4D...
1. Using the SNHookClass (which is what's described above) and...
2. Using some combination of Read-/WritePluginInfo() (in stand-alone mode) and Read-/WriteRegInfo() when in License Server mode.
...the first method uses the "Personalize" dialog for your plugin's license key entry in stand-alone mode and lets your plugin's license keys be served by the License Server along with everything else (the user just pastes the appropriate multi-license key(s) you sell them into the License Server dialog).
I haven't used the second method myself, but as far as I can tell, this would be a more brute-force and/or more loosely connected method of doing it.  ie. this method stores all licenses locally (on each machine), so the (each) user would have to enter a license key on each machine.
If that's indeed the case, then you'll also be limiting the user to a single "serial package" unless you implement some method of storing/validating multiple 'potential' license keys (using the first method, they can register multiple license keys - one for each "serial package" - with the License Server and the server sends your plugin the one that matches the package in use).
Again, if you're not familiar with the License Server, you should go watch those videos on Cineversity to see how it is (can be) used.  A large company could potentially have multiple different serial packages set up, for different departments or laptops vs workstations or... whatever.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 17/04/2009 at 16:45, xxxxxxxx wrote:

Wow, you really did a good job in summing up all this multilicense stuff! Well done, thank you!

Greetings,
Jack

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 17/04/2009 at 23:10, xxxxxxxx wrote:

Thanks Jack - I'm glad someone found it useful :).  I think many/most developers are using the Read-/WritePluginInfo() method and this thread is mostly geared towards having your plugin's license key "served" by the License Server when using the SNHookClass method, but there's a fair bit that applies to either.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 21/04/2009 at 03:05, xxxxxxxx wrote:

Keith, thanks a lot for your efforts. This thread should answer most questions regarding CINEMA 4D R11 plugin serialization.

cheers,
Matthias

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 08/02/2010 at 10:04, xxxxxxxx wrote:

Originally posted by xxxxxxxx

   
   
     
     Mod: Hair :                           **[11-0-1017643]**       <<40300012345-AAAA-BBBB-CCCC-DDDD>>  
   

...the next part (enclosed in square brackets) is important.  The '11' is the C4D version, the '0' is the platform (Mac or PC, but generally no longer used - I think this can always be '0') and finally, the PluginID of the plugin being registered (ie. you need to insert your plugin's ID here).

First of all thanks for this overview! Very helpful. However, shouldn´t this rather say that this is a unique ID passed to the serial hook object´s Register() function? Otherwise it would seem impossible to register several plugins within one library (.cdl) for a license server environment. Can somebody confirm this just to make sure?

Btw. is there ANY way to test this? Is there a license server demo? I wouldn´t want to see myself giving out a plugin demo untested (I probably wouldn´t in the end).

Also I´d like to know something else (as regdate is invalid). WriteRegInfo(), on which machine is this written to (assuming it is called from within SNCheck())? On the individual client machines or on the machine the license server is installed? I assume the former but I´d like to make sure I get this correctly.

thanks in advance

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 08/02/2010 at 10:12, xxxxxxxx wrote:

Ah and another question, although that has already been answered I guess but if regdate is invalid and WriteRegInfo is not suitable to be used in conjunction with the SNHook class, then it seems that it´s impossible to provide customers with a demo. So the customer would require a seperate single c4d license to test a plugin before he can buy a license for a license server environment right?

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 09/02/2010 at 03:44, xxxxxxxx wrote:

However, shouldn´t this rather say that this is a unique ID passed to the serial hook object´s Register() function? Otherwise it would seem impossible to register several plugins within one library (.cdl) for a license server environment. Can somebody confirm this just to make sure?

Yes, a unique ID has to be passed because all SNHookClass is doing is to establish a hook into the Personalize dialog.

Btw. is there ANY way to test this? Is there a license server demo?

We are currently thinking about ways to provide developers with license server NFR versions.

Also I´d like to know something else (as regdate is invalid). WriteRegInfo(), on which machine is this written to (assuming it is called from within SNCheck())? On the individual client machines or on the machine the license server is installed? I assume the former but I´d like to make sure I get this correctly.

Yes, it's written to the client machine.

cheers,
Matthias

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 09/02/2010 at 03:46, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Ah and another question, although that has already been answered I guess but if regdate is invalid and WriteRegInfo is not suitable to be used in conjunction with the SNHook class, then it seems that it´s impossible to provide customers with a demo. So the customer would require a seperate single c4d license to test a plugin before he can buy a license for a license server environment right?

This seems to be an oversight on our side. I forwarded this as feature request / bug report.

cheers,
Matthias

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 09/02/2010 at 05:47, xxxxxxxx wrote:

thanks Matthias for clearing this. An NFR version would definetly be super helpful.
Ok, for now I´ll tell my LS customers that there´s no demo possible. Maybe they wait. 🙂

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/02/2010 at 08:19, xxxxxxxx wrote:

Note that 11.5 and up now allow you to manually enter a serial number for a plugin using SNCheck if it's not provided by the License Server.

I'm happy to test license server compatibility here at MAXON USA for anyone who can't get their hands on it. Just send me a PM.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/02/2010 at 09:16, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Note that 11.5 and up now allow you to manually enter a serial number for a plugin using SNCheck if it's not provided by the License Server.

Hi Rick,

could you elaborate on this? I am not sure I fully understand this. Thanks

Originally posted by xxxxxxxx

I'm happy to test license server compatibility here at MAXON USA for anyone who can't get their hands on it. Just send me a PM.

Superb. Thanks for the support. I´ll probably get in touch with you on this directly next week then.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 20/02/2010 at 06:54, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Riptide Pro [11-0-1022532] _<__>
...the XOXO partwould be replaced by a 16 character generated license key

Just to make sure, the XOXO part does not explicitly need to be 16 characters in length right? It could also be more or less and may contain digits and characters right?

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 23/02/2010 at 02:25, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Originally posted by xxxxxxxx

Riptide Pro [11-0-1022532] <<RipPro12345-XOXOXOXOXOXOXOXO>>

...the XOXO partwould be replaced by a 16 character generated license key

Just to make sure, the XOXO part does not explicitly need to be 16 characters in length right? It could also be more or less and may contain digits and characters right?

As far as I know, your statement above is correct (within reason)... my license keys just happen to be 16 characters. I'm not sure if there's a fixed / practical upper limit on the length though.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 07/07/2010 at 08:30, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Originally posted by xxxxxxxx

Ah and another question, although that has already been answered I guess but if regdate is invalid and WriteRegInfo is not suitable to be used in conjunction with the SNHook class, then it seems that it´s impossible to provide customers with a demo. So the customer would require a seperate single c4d license to test a plugin before he can buy a license for a license server environment right?

This seems to be an oversight on our side. I forwarded this as feature request / bug report.cheers,Matthias

Hi Matthias,

Do you know if this issue (can't provide evaluation/demo plugins for License Server use) was ever addressed? I am currently working with a client and trying to determine some means of them purchasing a single test/evaluation copy, before they make the big purchase.

Thanks,

Keith