Jump to content
Mike Torrettinni

What options do I have to control custom releases?

Recommended Posts

I have a project that sometimes I need to control which features, menus are released (enabled) for some customers. For example I have a 'control' section in Project source, like this:

// control Main Menus
EnableVisioMenu := false; // Customer A
EnableDrawingMenu := false;  // Customer B

// control PopupMenu options
EnableCntxt_ImportFromVision := false; // ???
...

So, when I need a special version, I just set the relevant to True and build version for that specific Customer.

 

But the problem is, that once it's build, I don't know exactly which version it is... the project.exe file doesn't have this info. So, unless I run it, I don't know which version it is.

 

How do others control different, customized releases? Any advice how to improve this?

 

I use Delphi 10.2, and I build from IDE.

 

Share this post


Link to post

Hi,

 

There are a few options. Depending on your project, one might be a better choice than the other. (no particular order)

 

1) Use IFDEF. If you have a centralized unit where all those options are assigned, you can create in project manager a Release Customer A, Release Customer B,... , etc.
In each project configuration option, you should add a conditional define such as __CUSTOMER_A__, __CUSTOMER_B__, ...etc.
Your unit(s) will get a bunch of $IFDEFs :

// control Main Menus
{$IFDEF __CUSTOMER_A_} EnableVisioMenu := false;{$ENDIF} // Customer A 
{$IFDEF __CUSTOMER_B_} EnableDrawingMenu := false;{$ENDIF}  // Customer B

// control PopupMenu options
EnableCntxt_ImportFromVision := {$IFNDEF __CUSTOMER_C} false {$ELSE} true{$ENDIF}; // ???
...

As you can see, the more customers you get, the more difficult it will be to maintain such spaghetti, but it gets the job done.

 

2) Use an encrypted external configuration file
The file gets constructed according to each customer, the executable remains the same. The only difference is the config file. When you deliver your application, this file goes together. If you absolutely need to keep things in one file, you might consider generating a resource file (.RC) that will be included with your executable. Be aware that some anti-virus might show false positives. The file itself can be very simple, such as an INI file. As long as it's encrypted, it will do it's job.

 

3) More sophisticated license manager that will allow to handle properly many customers.

 

  • Thanks 1

Share this post


Link to post
2 hours ago, Mike Torrettinni said:

But the problem is, that once it's build, I don't know exactly which version it is... the project.exe file doesn't have this info. So, unless I run it, I don't know which version it is.

You could put that information in your program's Version info.  Define an .rc file that builds the version details conditionally.  Then use compiler conditionals to control which features are turned on/off in code, and which details are shown/hidden in the version info when the .rc file is compiled.

 

  • Thanks 1

Share this post


Link to post
1 hour ago, Clément said:

1) Use IFDEF. If you have a centralized unit where all those options are assigned, you can create in project manager a Release Customer A, Release Customer B,... , etc.
In each project configuration option, you should add a conditional define such as __CUSTOMER_A__, __CUSTOMER_B__, ...etc.
Your unit(s) will get a bunch of $IFDEFs :

Interesting, I didn't know I can set new build configurations in Project manager.

Share this post


Link to post
6 minutes ago, Remy Lebeau said:

You could put that information in your program's Version info.  Define an .rc file that builds the version details conditionally.  Then use compiler conditionals to control which features are turned on/off in code, and which details are shown/hidden in the version info when the .rc file is compiled.

 

I never tried that, the .rc file for version info. But I did notice now that I can Add Key to the Version info... my custom details. Thanks!

Share this post


Link to post

Instead of building separate executables, I suggest building one executable and leveraging feature toggles through licensing schemes or phone-home type methods

  • Like 2

Share this post


Link to post
4 hours ago, Darian Miller said:

Instead of building separate executables, I suggest building one executable and leveraging feature toggles through licensing schemes or phone-home type methods

Ok, maybe I can make it work, will think about it. One concern is on first run, when they can (or not yet) enter license details. So, until they enter license detail, at this time there is no control available based on license. I don;t force the license to be entered, so until they do, I can't control the project features.

Share this post


Link to post
16 hours ago, David Heffernan said:

You really want to do this in an automated way, so that you can build in a scripted fashion. 

This is a big change, as I've never tried it and from google search it seems quite tricky to make it work - first time.

Edited by Mike Torrettinni
clarification

Share this post


Link to post
9 hours ago, Mike Torrettinni said:

Ok, maybe I can make it work, will think about it. One concern is on first run, when they can (or not yet) enter license details. So, until they enter license detail, at this time there is no control available based on license. I don;t force the license to be entered, so until they do, I can't control the project features.

Sure you can. Give them the bare essentials, until a license is purchased. Or give them the maximum for 10 days, or whatever.

Share this post


Link to post

I finally made some progress on this and am using this solution:

https://stackoverflow.com/a/8509206/5198394

 

So, I use ExtraDefines keyword that inserts new define keyword used in msbuild. The problem is I need 2! 🙂 extra defines.

It works OK when I set it like this:

 

Project settings: ...$(ExtraDefines);$(ExtraDefines2);...

msbuild: "Config=release;ExtraDefines=CustomerA;ExtraDefines2=VISIO"

 

This is probably not used that often, but does anybody have a solution to insert multiple defines into single ExtraDefines? I tried this:

 

Project settings: ...$(ExtraDefines);...

msbuild: "Config=release;ExtraDefines=CustomerA;VISIO"

 

msbuild complains:

MSBUILD : error MSB1006: Property is not valid.
Switch: VISIO

 

I tried all sorts of combinations, like:

"Config=release;ExtraDefines=(CustomerA;VISIO)"

"Config=release;ExtraDefines=(CustomerA;$VISIO)"

...

same error about Property not valid.

 

Any suggestions?

Share this post


Link to post
On 7/18/2019 at 2:03 AM, Mike Torrettinni said:

Ok, maybe I can make it work, will think about it. One concern is on first run, when they can (or not yet) enter license details. So, until they enter license detail, at this time there is no control available based on license. I don;t force the license to be entered, so until they do, I can't control the project features. 

Just disable all features that will be working for licensed users only.

 

On 8/1/2020 at 9:20 PM, Mike Torrettinni said:

So, I use ExtraDefines keyword that inserts new define keyword used in msbuild. The problem is I need 2!

Check out lower answer in that SO topic

 

Btw, if you won't encrypt your code and use some sly tricks, it would be quite easy to detect all these `if customerA` places and make the app fully functional

Edited by Fr0sT.Brutal

Share this post


Link to post
2 minutes ago, Fr0sT.Brutal said:

Just disable all features that will be working for licensed users only.

This is now partially sorted out - now that I know I can control features from build process - ExtraDefines=Trial/Licensed/....

 

3 minutes ago, Fr0sT.Brutal said:

Check out lower answer in that SO topic

I think you are referring to creating multiple build configurations... thank you, I'm trying to stay away from that. For now! 🙂  I still use IDE for this, so not everything is fully automated; meaning I don't want to have too many build configurations. Debug and Release is enough; and 64bits are coming soon, so 4 will be enough.

 

I came up with a good-for-now ExtraDefines configuration in one keyowrd that covers what I need.

Share this post


Link to post
9 minutes ago, Mike Torrettinni said:

I think you are referring to creating multiple build configurations... thank you, I'm trying to stay away from that. For now! 🙂  I still use IDE for this, so not everything is fully automated; meaning I don't want to have too many build configurations. Debug and Release is enough; and 64bits are coming soon, so 4 will be enough. 

No I meant redefining an env var https://stackoverflow.com/a/38003499/1497831

Share this post


Link to post
On 7/16/2019 at 8:08 PM, Mike Torrettinni said:

I have a project that sometimes I need to control which features, menus are released (enabled) for some customers. 

I put all options into a single executable and at run time, I read a configuration file to set the features enable Boolean variables. The configuration file is an INI file which is protected by a digital signature the customer receive with his license. If he manually edit the INI file, then the signature is invalidated and the product fall back to demo mode.

 

Using this method, there is only one executable and producing a new release is easy: every customer get the features his license allow, nothing more, nothing less. Each customer can download the executable to get an update.

 

Since you use Delphi, you already know that Embarcadero is doing the same: The installer contains all versions, all languages. You get the pro version if you pais a pro license. You get the enterprise version if you paid for it. As easy as that.

  • Like 3

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×