There isn't a hot market for most business applications so theft is less of an issue than it is with "fun" things or more generalized applications that might be useful at home as well as at the office. A physical inventory is an example of something an employee might be tempted to steal for home use if it would work for a home inventory that is useful as a record for your insurance company.
The apps I sold were not shrink-wrapped so there was some training and custom support provided. I created what I called a token. It encoded a bunch of different things such as the expiration date, the number of concurrent audits, whether or not email was supported, and several other features. It also included a check digit which I placed at pos 8 out of 16 rather than as the last digit. We didn't try to control seat licenses. Six weeks before the token expired, the menu would change color and display an expiration warning.
I can't post any of the code but it wasn't really hard. There was a separate FE for generating the tokens. For each thing I encoded, I created an array of values and assigned logical meanings. I didn't use O, 0, or lower case l to avoid confusion. That left me 71 values for each character. Most of the options didn't take more than 3 so I allowed multiple values so that there might be 6 values that equated to expiration month but only 2 for exp day. In the "generation" phase, I generated a random number that generated a random value between 1 and 6 in the case of month. So if Jan was assigned values of 4, A, b, d, 8, Z and the random number was 3, then the token had a "b" for the month. On the other end, the translate table converted "b" to 1 for January.
The "token" was stored in a server table so it was available to all users. Each time the app opened, the expiration date was checked and the user was allowed to proceed or not. You can decide to allow read-only access if the token is expired and that is what we did. The data belonged to the user and we did not want to lock them out. However, the app would not do anything, including produce reports. It would just let you view client records but not change anything. The BE was not secured so the client could have access to his data directly if he wanted. The FE was locked down and technically no ordinary user would be able to get behind the scenes but the administrators could get into the BE but not the FE, that was locked down.