best method for trial app?

Discussion in 'Mac Programming' started by Darkroom, Jul 7, 2008.

  1. Darkroom Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #1
    what is the best, or most common way to set up a trail period for an app? would it be to write a hidden file using NSFileManager that sets a timestamp and checks the timestamp on each launch of the application?

    any other thoughts?
     
  2. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #2
    no one has any opinions on this? i assumed it would a hot topic...
     
  3. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #3
    When I write trial apps in Ruby, I do this.

    I pick my date in the future that I want the trial to expire. I convert this to float. Then at runtime, I get the current date, convert to float, and compare.

    A twist to this that I have done is to change the plist to set a flag that the trial period has been exceeded. This causes a persistent indicator to be set. That way, just a simple "set the clock back" won't get around my intent of expiring the trial period - the user would have to go to greater lengths to circumvent the trial period.

    Obviously, there are relatively simple ways to circumvent this, like setting the clock back prior to the period expiring. I added logic to check for this, like each time the program starts, set the current time in the plist, and if the current time was ever a time prior to the saved time, end the trial then and there.

    I think the next wave of trial-ending checks I develop will be across the net. I'll have the code "phone home" and use the clock on our server. This would require the user to have a network connection active, which, is not really inconvenient I guess, but could be limiting for a user.

    Actually, along this same line, I'm considering not even distributing the core part of the code, but just distributing a stub program that phones home to get itself at runtime (using AJAX). This would work not only for a trial period, but also to cut down on pirated code. Also, the user always gets the latest version of the code, and there's nothing for them to pirate, as their credentials get validated each time at runtime, and the code is never stored on their hard drive in a manner which is easy to duplicate.

    Todd
     
  4. Consultant macrumors G5

    Consultant

    Joined:
    Jun 27, 2007
    #4
    Some people have problem with their clock due to windows changing clock time, thus perhaps the difference has to be >24 hours to trigger.
     
  5. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #5
    i finally found an example online about this, but i'm having a difficult time making sense of it. it seems to me that it's only possible to choose an actual date for a trial to end, instead of a writing endDate=startDate+15days... also, when i changed the date and let the software expire, it still worked when i launched it again? plus, with this code, couldn't a user just delete the software and reinstall it to start a new trial since the trial code appears to be built in.

    main.m
    Code:
    #import <Cocoa/Cocoa.h>
    #import "ESSTimeTrialClass.h"
    
    int main(int argc, char *argv[])
    {
    	NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
    	[ESSTimeTrialClass timeTrialWithEndDate:[NSDate dateWithString:@"2007-05-12 13:37:00 +0200"] endMessage:@"This time trial is over. Please alter the source code to see how it works."];
    	[myPool release];
        return NSApplicationMain(argc,  (const char **) argv);
    }
    
    ESSTimeTrialClass.h
    Code:
    #import <Cocoa/Cocoa.h>
    
    
    @interface ESSTimeTrialClass : NSObject
    {
    	NSDate *endDate;
    	NSString *endMessage;
    	NSTimer *timer;
    	BOOL timerIsRunning;
    }
    + (ESSTimeTrialClass *)timeTrialWithEndDate:(NSDate *)date endMessage:(NSString *)aString;
    - (id)initWithEndDate:(NSDate *)date endMessage:(NSString *)aString;
    - (void)startTimer;
    - (void)endTimer;
    - (void)setEndDate:(NSDate *)date;
    - (void)setEndMessage:(NSString *)aString;
    @end
    
    ESSTimeTrialClass.m
    Code:
    #import "ESSTimeTrialClass.h"
    
    static ESSTimeTrialClass *myClass = nil;
    
    @implementation ESSTimeTrialClass
    
    + (ESSTimeTrialClass *)timeTrialWithEndDate:(NSDate *)date endMessage:(NSString *)aString
    {
    	if (date && aString)
    	{
    		if (!myClass)
    		{
    			myClass = [[ESSTimeTrialClass alloc] initWithEndDate:date endMessage:aString];
    		}
    		return myClass;
    	}
    	return nil;
    }
    
    - (id)initWithEndDate:(NSDate *)date endMessage:(NSString *)aString
    {
    	if (date && aString)
    	{
    		if (self = [super init])
    		{
    			[self setEndDate:date];
    			[self setEndMessage:aString];
    			timerIsRunning = NO;
    			[self startTimer];
    			return self;
    		}
    	}
    	return nil;
    }
    
    - (void)setEndDate:(NSDate *)date
    {
    	[endDate release];
    	endDate = [date retain];
    }
    
    - (void)setEndMessage:(NSString *)aString
    {
    	aString = [aString copy];
    	[endMessage release];
    	endMessage = aString;
    }
    
    - (void)startTimer
    {
    	if (![[[NSDate date] laterDate:endDate] isEqualToDate:endDate])
    	{
    		NSRunAlertPanel(@"This Software has expired",endMessage,@"OK",nil,nil);
    		[NSApp terminate:nil];
    	} else
    	{
    		if (!timerIsRunning)
    		{
    			timer = [[NSTimer scheduledTimerWithTimeInterval:[endDate timeIntervalSinceNow] target:self selector:@selector(quit:) userInfo:nil repeats:NO] retain];
    			timerIsRunning = YES;
    		}
    	}
    }
    
    - (void)endTimer
    {
    	if (timerIsRunning)
    	{
    		[timer invalidate];
    		[timer release];
    		timer = nil;
    		timerIsRunning = NO;
    	}
    }
    
    - (void)quit:(NSTimer *)aTimer
    {
    	NSRunAlertPanel(@"This Software has expired",endMessage,@"OK",nil,nil);
    	[NSApp terminate:nil];
    }
    
    - (void)dealloc
    {
    	NSLog(@"aha");
    	[endMessage release];
    	[endDate release];
    	if (timerIsRunning)
    	{
    		[timer invalidate];
    		[timer release];
    	}
    	[super dealloc];
    }
    
    @end
    
     
  6. yeroen macrumors 6502a

    yeroen

    Joined:
    Mar 8, 2007
    Location:
    Cambridge, MA
    #6
    Whatever you do, don't write the expire or reference date ( in seconds since the epoch, e.g.) in plaintext to a (hidden) file somewhere on disk.

    This is how I got a free copy of Adobe Lightroom by merely editing these values (change a leading digit in the number, say). My trial period will now last for 6000+ days. Thanks Adobe!
     
  7. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #7
    wow, i'm well lost on this one... if someone can post a small working example of how to do this properly and effectively i'd be super grateful... :eek:
     
  8. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #9
    if anyone of you who knows how to do this effectively and properly could post a small sample i would be very grateful...
     
  9. Mac Player macrumors regular

    Joined:
    Jan 19, 2006
    #10
    Every simple way to do that will be cracked in 5 minutes. Watanabe's apps proved to be extremely resilient to cracking.
     
  10. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #11
    sure, that would be great to have a strong uncrackable option, but i'm sure it would be very difficult to implement, and i'm not sure i'm advanced enough to even follow along with something so complex...

    also, i've realized that while developers are extremely upset to find their apps cracked on torrent sites, these people on the torrent sites wouldn't have bought it anyway, so it doesn't really matter...
     
  11. Krevnik macrumors 68030

    Krevnik

    Joined:
    Sep 8, 2003
    #12
    Usually it boils down to: how much time are you willing to spend, and how much in extra sales will it give you?

    Do not go to the lengths of making it overly complex or intrusive to the user, especially if it only means a hundred dollars in extra sales. Keep it simple, and use it to keep the user honest. Personally, anything in excess of that just wastes your time as a shareware programmer, and will get cracked quickly enough anyways.
     
  12. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
  13. springframework macrumors member

    Joined:
    Mar 31, 2008
    #14
    if you want to pay me ill make you a sample? work isn't free ... your weird asking for free work.



    since iphone has no windows explorer type thing, no usb access. basically no way to modify files on the phone. you can save the file where ever you want and not have to worry about it being modified.

    a different approach instead of a trial time period, is to allow them 10 times running the application.
     
  14. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #15
    ???... sample == example... i didn't ask if someone could write my application for me... like above, i found an example and posted it to this thread... someone may find it useful at some point, maybe i should attach my paypal account to that code snip :rolleyes:

    *flips you a quarter* now go write me some sample "work"... and make me a sandwich while your at it :p

    it's not an iphone app...

    allowing 10 times to run an app would require the same type of methods and hidden files to be written by NSFileManager as a 15 day trial would it not?
     
  15. springframework macrumors member

    Joined:
    Mar 31, 2008
    #16
    oh sorry, i got thinking this was only an iphone forum.

    u could try sqlite, u can't modify the .sql file with any stock mac program.
     
  16. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #17
    how did you find the reference text file for Adobe Lightroom? i guess it's pretty easy with the right software that would list all files that had been written to disk during install (i'm assuming there's an app that does that)...

    what file format would you suggest to write to disc if not .txt?... i mean, i'm using NSFileManager to writeToFile [[NSDate date] description] as a string (atomically:YES encoding:NSUnicodeStringEncoding error:NULL)... if i save it as a .plist file i could just take the file and change the extension to .txt to change the date that was set, then of course change it back to a .plist file... or whatever... that is if i didn't want to have to delete the hidden file every time the trail runs out - assuming, of course, that i found the hidden file.

    but i'd like to know truthfully: if you weren't able hack the date reference file for Adobe Lightroom, would you have really bought it?
     
  17. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #18
    Sample Code Attached

    so i managed to figure out how to do this... it took me all night, but i'm glad i have at least something to work with now... it's perhaps not the most optimized way of doing this, since the NSTimer is running every second, but it seems to work (and there are no memory leaks!)

    files are attached. open in xcode and build the project yourself. the app writes a date/time stamp file (.txt) to the desktop, and employs NSTimer as a listener while the app is running. times are displayed in the window to show it works. in real world use of this code, the file with date/time stamp would be a hidden file written somewhere on the user's computer, and maybe not as a plain text file as Yeroen suggested earlier.

    i would appreciate feedback if anyone has any thoughts or suggestions.

    [EDIT] i found that my attached code wasn't stopping when the time ran out because of my original if statement, so i changed it to: if (daysUsed >= 0)... now it works properly... the updated attached file is now set at 0.0002 days (which is about 19 seconds or so) so clearly anyone who wants to use this will have to change that number to the amount of days they want their serial to last (IE:15 for fifteen days)... finally, depending on how long you trail is (or isn't), it's really not that necessary to run the timer ever second... once every 5 of 10 minutes should be fine, or even once an hour while the app is running.
     

    Attached Files:

  18. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #20
    thanks for that... but i'm personally going to use Aquatic Prime for serialization... it's all automated with PHP scripts and paypal for your personal site, and uses drag and drop license files instead of serial numbers, which i find much more interesting... it's a really great framework... and it's free too! (although i'm totally going to donate my first sale to Lucas Newman who developed Aquatic Prime)
     

Share This Page