Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss. print.
MAKE A DEMO VERSION OF YOUR APP

Recently I downloaded a demo version of a very nifty tool that does some good work in documenting complete projects under VFP. One of the very nifty things that I noticed was the fact that this demo version had a countdown mechanism that actually had no extra files installed on my machine. No OCX’s no DLL’s or whatever. This really got my interest, as I am now working on some apps as well that I would like to sell commercially. So, having such a solution would really help.

I thought about how to do this and I came up with the solution I will describe here.

The keys to the solution

Key 1 and an extra tip
One of the tips is Dale Dedoroy's tip how to protect you class library. Basically it comes down to compiling the library, opening it as a table and replacing all the method fields with chr(0). One more tip I will give you here is to add something to the header of all the methods.


IF .F.
    _refox_ = (SomeLengthyPassWord)
ENDIF

This will prevent ReFox from decompiling any code. This, and Dale’s tip give you double protection. (OK, this was for free).

Key 2
Now try as follows. Go to a directory where you have a vcx (in the following example referred to as that_vcx). Next, type in the command window:

SET CLASSLIBRARY TO that_vcx
USE That_vcx.vcx && note the .vcx extension to open it as a table.

Interesting here is the fact that you can add the class-library to the available libraries AND open it as a table at the same time. This was the first part of my solution.

Key 3
Second is something Eric den Doop once told on this site about STRTOFILE(). He uses it to install for example .OCX and .DLL files he needs for his app on the fly. He includes a DBF with a memo field in his EXE and at startup does some checking on the existence of those controls. If the required files are not available, he 'extracts' the files from the memo field with STRTOFILE().
The thought that came up with me was: “Why not store a DBF file in the memofield of a DBF?” OK, I admit, maybe somebody has to be a bit twisted to think that way but hey, that’s me…


Key 4
Any file (.frx, .vcx, .dbc et cetera) of VFP has a field where you can store any data you would like. That field is the user-field. My next thought was to store a dbf into the user-field with the FILETOSTR() function. That wasn’t too hard to achieve. The complete procedure for this demo-demo is done in the init of the .VCX. Here’s the code:

IF .F.
    _REFOX_ = "B231012l44_COUNTDOWNINIT"
ENDIF
**********************************************************************
* Program....: COUNTDOWN.INIT
* Version....:
* Author.....: B.L.P.M. Lutgerink
* Date.......: 12 September 2002, 09:52:01
* Notice.....: Copyright © 2002, Vektis BV, All Rights Reserved.
* Compiler...: Visual FoxPro 07.00.0000.9465 for Windows
* Abstract...:
* Changes....: BL, created September 12, 2002
* Parameters.:
* Purpose....:
**********************************************************************
LOCAL lcAliasName, lcFieldName
* Open the classlib as a table
* Use the classlib property for that.
*
USE (THIS.CLASSLIBRARY) IN 0
* 
lcAliasName = JUSTSTEM((THIS.CLASSLIBRARY))
lcFieldname = lcAliasName + ".User"
GO TOP IN (lcAliasName)
* create a file from the userfield content.
*
STRTOFILE(&lcFieldname.,"sysinfo.dbf")
USE sysinfo IN 0
* one record only one field only.
*
IF sysinfo.nSysInfo > 0 THEN
    MESSAGEBOX("You have "+TRANSFORM(sysinfo.nSysInfo)+" Times left",64,_SCREEN.CAPTION)
    REPLACE sysinfo.nSysInfo WITH sysinfo.nSysInfo-1
    USE IN SELECT("sysinfo")
    REPLACE (lcFieldname) WITH FILETOSTR("sysinfo.dbf") IN (lcAliasName)
    ERASE sysinfo.*
ELSE
    MESSAGEBOX("Demo cannot run anymore"+CHR(13)+"contact sysop",48,_screen.Caption)
    USE IN SELECT("sysinfo")
    ERASE sysinfo.*
ENDIF
USE IN SELECT((lcAliasName))

Some considerations
The above code is, as you all can see very basic. No checking was done on registration, no efforts were taken on encrypting the table (sysinfo.dbf) itself. That is beyond the purpose of this article. So, for a complete version to your own liking some creative thinking is required from your side. I would hate it if I was accused from making you fellows lazy.
Another thing one could do is simply add an (encrypted) counter to the userfield. Registering users could be done through a table as well, even the same table already stored in the userfield, hence my prevalation for storing a table in the user-field. The logic for the registration-key can be created all by yourself as well, One could think of a combination of username, city and country, mix it up and make a key out of it. Who knows, maybe an idea for an article from one of the visitors here? I will let my mind go over this anyway.

One last word and a little warning
The first tip I started with, protection of the VCX from reading it, was given because the VCX and the VCT that comes with it, cannot be included in the EXE that your customers install. Those files have to be installed separately. Otherwise the table that the VCX actually is will be read-only. I suggest that there is some code in the actual application that checks for the existence of these files (vcx and vct) first. This, of course, gives the possibility to encrypt and decrypt those files on-the-fly as well.

Tip
For more info on using the crypt API some great samples come along with VFP. See the solutions database for samples. Also, in the FoxPro Advisor of September 2002 on page 16, a fine article is published. The author is Daryl More. The code published there is applicable to versions 3, 5, 6 and 7 of VFP. As is the code of this article.

Download code
In the download section of this fine site you will find a zip file containing a class-library named appsystem.vcx. This library has a class countdown in it, containing the code from this article (INIT). I choose this library-name as a sample how you can mislead people by a simple name. I suggest you give it a name that says more about the app that is supposed to accompany this VCX.

Let me know how you think about this article. Happy Foxiting.

ABOUT THE AUTHOR: BOUDEWIJN LUTGERINK

Boudewijn Lutgerink Programming is one of the many hobbies of Boudewijn. He has worked with computers since 1985 and is the author of two books from Sybex. He has a weblog at http://weblogs.foxite.com/boudewijnlutgerink.

FEEDBACK

manoj @ 6/15/2008 7:56:53 PM
thanks for support to making this code.
but i told u in dos based how may i protect my code. to make demo version.

YOUSFI BENAMEUR @ 6/28/2008 3:39:25 PM
Hello Mr Boudjewin
I read your article and i send you a reply like this.
/////////////////////////////////////////////////////////
CLEAR all

IF .F.
_REFOX_ = "B231012l44_COUNTDOWNINIT"
ENDIF

LOCAL lcAliasName, lcFieldName
* Open the classlib as a table
* Use the classlib property for that.
aa=GETFILE('vcx')

USE &aa IN 0
brow
*
lcAliasName = JUSTSTEM((aa))
lcFieldname = lcAliasName + ".User"
*messagebox(lcFieldname+":"+&lcFieldName)
GO TOP IN (lcAliasName)
* create a file from the userfield content.
STRTOFILE(&lcFieldname.,"sysinfo.dbf")
USE sysinfo IN 0
SELECT sysinfo

REPLACE nsysinfo WITH nsysinfo+1 && stay this value constant all times and you can work in peace !!
* one record only one field only.

*
IF sysinfo.nSysInfo > 0 THEN
MESSAGEBOX("You have "+TRANSFORM(sysinfo.nSysInfo)+" Times left",64,_SCREEN.CAPTION)
REPLACE sysinfo.nSysInfo WITH sysinfo.nSysInfo-1
USE IN SELECT("sysinfo")
REPLACE (lcFieldname) WITH FILETOSTR("sysinfo.dbf") IN (lcAliasName)
ERASE sysinfo.*
ELSE
MESSAGEBOX("Demo cannot run anymore"+CHR(13)+"contact sysop",48,_screen.Caption)
USE IN SELECT("sysinfo")
ERASE sysinfo.*
ENDIF
USE IN SELECT((lcAliasName))

//////////////////////////////////////////
i am a new member of foxite.com
give me some feed back at my email : thank you !
benameuryousfi1@gmail.com

Ronald Weinrich @ 7/10/2008 11:23:45 AM
Hi Boudewijn Lutgerink,
could you tell me how to change the sysinfo.nSysInfo if I like to limit it to 30?
Where to I have to put the 30?
In the meantime I run the code (uncomment REPLACE..)
...
USE sysinfo IN 0
*REPLACE sysinfo.nSysInfo WITH sysinfo.nSysInfo+31
IF sysinfo.nSysInfo > 0 THEN
...
before I deliver.

Tia
Ron



Your Name: 
Your Feedback: 

Spam Protection:
Enter the code shown: