Jump to content

About licensing AutoLISP program


lido

Recommended Posts

Please advise me about the step by step procedure, algorithm, etc., to license an AutoLISP program (VLX file) to the end user with a trial period of 30 days, during which the user can test the demo version of the program.

Thank you

Link to comment
Share on other sites

There are various ways of testing a date via lisp, lee-mac has a check date via internet this removes the PC clock which can be wound back. you just IF date > expire date then a exit defun use (Exit) last. This question has been posted here before.

Link to comment
Share on other sites

BTW one could do this aswell, by putting a fixed (expiration) date :

(cond 
  ( (>= (read (substr (rtos (getvar 'cdate) 2 5) 1 8)) 20181226) (prompt "\nProgram Expired !") (princ) ) ; expiration
  (
    ; .. Define functions for our program
    (defun C:MyHandsomeProgram nil
      ; ...
    ); defun 
    (defun C:AnotherHandsomeProgram nil
      ; ...
    ); defun 
    (defun SomeFancySubFun ( args )
      ;...
    ); defun
    ; ...
  )
); cond

Although one thing I couldn't figure out yet, was how to alert when the program expires in X days, when the year or the month is changed -

(
  (lambda ( cdate expdate / )
    (cond 
      ( (and (= 3 (- expdate cdate)) (alert "\nProgram will exipre in 3 days.")) )
      ( (and (= 2 (- expdate cdate)) (alert "\nProgram will exipre in 2 days.")) )
      ( (and (= 1 (- expdate cdate)) (alert "\nProgram will exipre in 1 day.")) )
      ( (>= cdate expdate) (alert "\nProgram Expired !") (princ) ) ; expiration
      (t
        
        (defun C:test ( / )
          (alert "Hello World")
          (princ)
        ); defun C:test
        
        ; .. Define functions for our program
      ); t
    ); cond
  ); lambda
  (read (substr (rtos (getvar 'cdate) 2 5) 1 8))
  20190131
)

Say the expiration date is on 2019.02.01 and the current date is 2019.01.30, so we'd like to alert that there are 2 days remaining. 😕

 

Edited by Grrr
Link to comment
Share on other sites

58 minutes ago, Grrr said:

Say the expiration date is on 2019.02.01 and the current date is 2019.01.30, so we'd like to alert that there are 2 days remaining. 😕

 

The easiest way is to use the contiguous Julian date system, e.g.:

(
    (lambda ( date expdate / dif )
        (if
            (cond
                (   (not (or dtoj (and (load "julian.lsp" nil) dtoj))))
                (   (<= (setq dif (- (fix (dtoj expdate)) date)) 0)
                    (alert "Program has expired.")
                )
                (   (progn (alert (strcat "Program will expire in " (itoa dif) " day" (if (= 1 dif) "." "s."))) t))
            )
            (progn
                (defun c:test ( )
                    (alert "Hello World!")
                    (princ)
                )
            )
        )
    )
    (fix (getvar 'date))
    20190131
)

Here, the Express Tools' dtoj function is only used to make it easier to specify the expiration date in the code - you can easily remove this reliance by specifying the expiration date as a Julian date directly in the code.

 

Note that this approach is still susceptible to the user changing the system clock - hence the suggestion to use my Internet Time function above.

Edited by Lee Mac
  • Like 2
Link to comment
Share on other sites

Can I add a MacAddress?

 

(
    (lambda ( date expdate / dif )
        (if
            (cond
                (   (not (or dtoj (and (load "julian.lsp" nil) dtoj))))
                (   (<= (setq dif (- (fix (dtoj expdate)) date)) 0)
                    (alert "Program has expired.")
                )
            ( (not get_macaddress) (princ "\nFunction get_macaddress is not loaded.") )
                    ( (not (eq MyMacAddress (get_macaddress))) (princ "\nYou have no permission to run this routine.") )
                (   (progn (alert (strcat "Program will expire in " (itoa dif) " day" (if (= 1 dif) "." "s."))) t))
        
            )
            (progn
                (defun c:test ( )
                    (alert "Hello World!")
                    (princ)
                )
            )
        )
    )
    (fix (getvar 'date))
    20190131
)

Edited by ssdd
  • Thanks 1
Link to comment
Share on other sites

25 minutes ago, Lee Mac said:

The easiest way is to use the contiguous Julian date system, e.g.:

 

Wow nice one, Lee!

 

33 minutes ago, Lee Mac said:

Here, the Express Tools' dtoj function is only used to make it easier to specify the expiration date in the code - you can easily remove this reliance by specifying the expiration date as a Julian date directly in the code.

 

Well I could also violate a bit Autodesk's terms of use, by appending the dtoj function definition into the expiration date wrapper.  :playing:

Ofcourse this doesn't sound like the right thing to do, but on the other hand the algorithm could be replicated (if its not already somewhere on the internet) and overall doesn't do any harm.

 

41 minutes ago, Lee Mac said:

Note that this approach is still susceptible to the user changing the system clock - hence the suggestion to use my Internet Time function above.

 

I remember we were doing such clock-adjusting back in the 90's in order to run some expired programs :D

I find your LM:InternetTime great, but theres one thing to keep in mind, since when defined the subfunction remains "public" -

It must be defined while running the expiration wrapper...else one could simple redefine your sub in order to bypass the checks like so:

(defun LM:InternetTime ( format )
  "01.01.99" ; "MO.DD.YY"
)

Assuming the "bad" guy nailed the date format.

Thats why I try to keep some stuff localised/private within a scope.

 

Thanks Lee!

 

  • Thanks 1
Link to comment
Share on other sites

4 minutes ago, Grrr said:

I find your LM:InternetTime great, but theres one thing to keep in mind, since when defined the subfunction remains "public" -

It must be defined while running the expiration wrapper...else one could simple redefine your sub in order to bypass the checks like so:


(defun LM:InternetTime ( format )
  "01.01.99" ; "MO.DD.YY"
)

Assuming the "bad" guy nailed the date format.

Thats why I try to keep some stuff localised/private within a scope.

 

If you were going to the trouble of implementing an trial license, you would of course compile the entire application to a separate-namespace vlx, meaning that the definition of the LM:InternetTime function could not be modified (or, rather, any definition would not affect the definition within the vlx namespace) as it resides outside of the document namespace.

  • Like 1
Link to comment
Share on other sites

9 minutes ago, Lee Mac said:

you would of course compile the entire application to a separate-namespace vlx, meaning that the definition of the LM:InternetTime function could not be modified

 

Oh wow seems like you already thought about this problem! 👍

..and I've forgot to like your posts, so doing it right now!

Link to comment
Share on other sites

40 minutes ago, ssdd said:

Can I add a MacAddress?

 

Indeed you can - consider a function such as the following:

;; MAC Addresses  -  Lee Mac
;; Returns a list of MAC Addresses for all installed network adaptors

(defun LM:macaddresses ( / err qry srv wmi )
    (if (setq wmi (vlax-create-object "wbemscripting.swbemlocator"))
        (progn
            (setq err
                (vl-catch-all-apply
                    (function
                        (lambda ( / rtn )
                            (setq srv (vlax-invoke wmi 'connectserver)
                                  qry (vlax-invoke srv 'execquery "select macaddress from win32_networkadapter where macaddress is not null")
                            )
                            (vlax-for itm qry (setq rtn (cons (vlax-get itm 'macaddress) rtn)))
                        )
                    )
                )
            )
            (foreach obj (list qry srv wmi)
                (if (= 'vla-object (type obj))
                    (vlax-release-object obj)
                )
            )
            (if (vl-catch-all-error-p err)
                (prompt (vl-catch-all-error-message err))
                err
            )
        )
    )
)

 

Edited by Lee Mac
  • Thanks 1
Link to comment
Share on other sites

13 minutes ago, Grrr said:

 

Oh wow seems like you already thought about this problem! 👍

..and I've forgot to like your posts, so doing it right now!

 

Thanks! 🍺

Link to comment
Share on other sites

Mac address

PC Date

Internet date

Hard disk ID

Regapp entry

Autocad serial number

Ping a web server

 

Lots of methods available 

 

Oh yeah the phone call "the software is not working how do I fix ?" bottom line the end user tried to install on another computer without paying.

  • Thanks 1
Link to comment
Share on other sites

Thank all of you guys for your answers.

Bellow, I will try to analyze the options. Please correct me if I'm wrong.

 

If we were talking about the date, finding the current date is not enough. It is important to check the difference between the date of installing the program and the current one (<=30, in days).  So the installing date must be saved. Options:

1. Use the registry key from the installation kit (NSIS, for example).

2. Create a file as hidden as possible, containing the date of the first launch of the program (with AutoLISP).

In my opinion, both variants are weak and do not provide an effective protection system.

Another approach is to not check the 30 days trial period. In this case the program can be used as usual, with some limitations until the user decides to purchase it.

 

Now, with regard to how licensing can be done, at least at this time, the licensing option is offline. What data should be provided by the user?

Let's see the vendor's options for licensing:

1. Identify hardware components: HDD serial number, BIOS data, MAC address, etc.: 

     PROS: strong level of protection.

     CONS: replacing a hardware component will result in the license being canceled.

2. Using (Auto)CAD system variables:

   a) _PKSER:

        PROS: level of protection under (Auto)CAD.

        CONS: if (Auto)CAD is cracked, there is no control over the program.

  b) LOGINNAME:

        PROS: same as 2a above.

        CONS: same as 2 above; only the licensed user can use the program (case of multiple users for the same PC).

3. Any combination between option 1 and option 2 above.

 

Concluding, let's say that I chose option 2a. Considering this option, in my opinion, the type of (Auto)CAD license should be checked: Standalone or Network (multi-users); the number of licenses of the program should be equal to the number of subscription seats, if the (Auto)CAD license type is Network.

Under AutoCAD, the system variable _LINFO (undocumented) provide same information, as follow:

 - AutoCAD 2005 Network license: (getvar "_LINFO") return "ADLM Network License Granted. Connects: 1"

 - AutoCAD 2015 Standalone license:  (getvar "_LINFO") return  nil.

I do not know if the system variable _LINFO exists and how it behaves under other CAD platforms.

 

 

 

Questions:

1. The (Auto)CAD license type (Standalone or Network) can be found out otherwise than by using system variable _LINFO?

2. How to find the number of subscription seats using AutoLISP in case of (Auto)CAD Network license?

Link to comment
Share on other sites

lido

If you need good protection, you need to use a ready-made solution.
Write a request to this company: http://www.star-force.com/
They make protection on programs, and they make protection on Lisp.
All your protection requirements they can do is not a problem.
I have been using this protection for a long time.

  • Thanks 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...