Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Darkroom

Guest
Original poster
Dec 15, 2006
2,445
0
Montréal, Canada
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?
 
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
 
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.

Some people have problem with their clock due to windows changing clock time, thus perhaps the difference has to be >24 hours to trigger.
 
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
 
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!
 
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:
 
Every simple way to do that will be cracked in 5 minutes. Watanabe's apps proved to be extremely resilient to cracking.
 
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...
 
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.
 
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.
 
if you want to pay me ill make you a sample? work isn't free ... your weird asking for free work.

???... 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

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.

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?
 
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.
 
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!

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?
 
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.
 

Attachments

  • (UPDATE)DateSetAndRead.zip
    55.4 KB · Views: 100
  • Picture 1.png
    Picture 1.png
    43.8 KB · Views: 95

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)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.