Mike Torrettinni 198 Posted July 16, 2019 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
Clément 148 Posted July 16, 2019 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. 1 Share this post Link to post
Remy Lebeau 1396 Posted July 16, 2019 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. 1 Share this post Link to post
Mike Torrettinni 198 Posted July 16, 2019 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
Mike Torrettinni 198 Posted July 16, 2019 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
David Heffernan 2345 Posted July 17, 2019 You really want to do this in an automated way, so that you can build in a scripted fashion. 2 Share this post Link to post
Darian Miller 361 Posted July 17, 2019 Instead of building separate executables, I suggest building one executable and leveraging feature toggles through licensing schemes or phone-home type methods 2 Share this post Link to post
Mike Torrettinni 198 Posted July 17, 2019 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
Mike Torrettinni 198 Posted July 17, 2019 (edited) 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 July 17, 2019 by Mike Torrettinni clarification Share this post Link to post
Sherlock 663 Posted July 18, 2019 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
Mike Torrettinni 198 Posted August 1, 2020 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
Fr0sT.Brutal 900 Posted August 6, 2020 (edited) 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 August 6, 2020 by Fr0sT.Brutal Share this post Link to post
Mike Torrettinni 198 Posted August 6, 2020 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
Fr0sT.Brutal 900 Posted August 6, 2020 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
Mike Torrettinni 198 Posted August 6, 2020 42 minutes ago, Fr0sT.Brutal said: No I meant redefining an env var https://stackoverflow.com/a/38003499/1497831 Thanks, will have a look. Share this post Link to post
Mike Torrettinni 198 Posted August 6, 2020 1 hour ago, Fr0sT.Brutal said: No I meant redefining an env var https://stackoverflow.com/a/38003499/1497831 Yes, works as expected - multiple defines accepted! Share this post Link to post
Fr0sT.Brutal 900 Posted August 6, 2020 As I said there, that answer deserves much more upvotes)) Share this post Link to post
FPiette 383 Posted August 9, 2020 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. 3 Share this post Link to post