Probably the most foolproof way of licensing (when done right) is through something the user physically has - some kind of hardware dongle.
- very hard to copy/duplicate
- not dependent on network access
- tamper-resistant (compared to software)
- user-friendly (when working correctly)
- licence count enforcement (can't easily plug 1 dongle into 10 machines at once)
Of course, it has also numerous disadvantages:
- expensive to produce
- hard to repair/replace
- actually requires you to communicate with the dongle in a cryptographically secure way - any kind of
if(dongle_ok()) { do_stuff() }
is an invitation for crackers to patch that over to if (1) { do_stuff() }
...
- ...which will require special drivers...
- ...maybe even a special interface (I still have a LPT dongle, but no LPT ports; USB<->LPT sucks)
- don't even think of hooking it up to a virtual machine (although peripheral support is better in VMs nowadays)
- support hell (is it connected? is it not broken? is the driver not broken? are the signatures/keys right and unexpired?)
- fragile, esp. if it sticks out of the computer and/or has destructive anti-tamper mechanisms
- may break communication with other peripherals (esp. those "pass-through" things were notorious for this)
For most programs, the disadvantages far outweigh the advantages; however, if you're making expensive, complex software (think "production plant control"), your clients are rather cavalier about licensing (in other words, "would buy a single copy (crack it if necessary) and run it on 50 machines if they could get away with it"), and lawsuits are impractical (take too long, you don't have much evidence, uncertain outcome), this may be useful. (I didn't say simple, did I?)