Originally wrote this up as a reply to a thread where the OP had asked for a way to check to see if the user had used their app for X days... The problem with most approaches is that they use date comparisons. That means the user can get around it by moving the system date back.
Here's something I threw together... it's nothing complicated, still has a loop hole, but for as basic as it is, not too bad. Rather than just storing the install or first-run date, I grab the current date, hash it, and check to see if the hash exists in the settings collection. If not, and we still have "slots" open... then it's considered to be a new date of usage, and the hash gets added to the collection. Once all of the slots have been used, the trial period is over and the function returns false.
Written in VB2008... should work in 2005, and will work in 2010 (although it's only tested in vb2008)
First the setup - From Project properties, go to the settings and create a user scoped setting "UsageDates" Set the type to "Specialized.StringCollection" and leave the default value blank.
Then add these two functions somewhere where your start up form or sub can get to them (like in the form itself, or the module where the Main sub is... where ever)
vb Code:
Private Function CheckDate(ByVal dateToCheck As Date) As Boolean 'In reality, CheckDate would get the date (current date) itself and not have it passed in Dim retValue As Boolean = False 'Fail safe, default to false Dim usageDatesLeft As Int16 = 3 ' set it to 4 just for testing 'Dim usageDatesLeft As Int16 = 30 ' set this to the number of days of application access 'Hash the date Dim hashedDate As String = HashDate(dateToCheck) 'Check to see if the hash value exists in the UsageDates 'Initialize the container if necessary If My.Settings.UsageDates Is Nothing Then My.Settings.UsageDates = New System.Collections.Specialized.StringCollection End If If My.Settings.UsageDates.Contains(hashedDate) Then 'then we are ok... it's already been checked retValue = True usageDatesLeft -= My.Settings.UsageDates.Count 'sanity check... if the system date is backed up to a previous date in the list, but not the last date If usageDatesLeft <= 0 AndAlso My.Settings.UsageDates.IndexOf(hashedDate) <> My.Settings.UsageDates.Count - 1 Then retValue = False End If Else If My.Settings.UsageDates.Count < usageDatesLeft Then My.Settings.UsageDates.Add(hashedDate) End If usageDatesLeft -= My.Settings.UsageDates.Count 'If not, and the remining count has "slots" open, add it If usageDatesLeft > 0 Then retValue = True Else 'If not and tree are no more slots, tell user, exit app retValue = False End If End If 'Display to the user how many days are remianing: MessageBox.Show(String.Format("You have {0} day(s) remaining.", usageDatesLeft)) Return retValue End Function Private Function HashDate(ByVal dateToHash As Date) As String 'Get a hash object Dim hasher As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create() 'Take date, make it a Long date and hash it Dim data As Byte() = hasher.ComputeHash(System.Text.Encoding.Default.GetBytes(dateToHash.ToLongDateString())) ' Create a new Stringbuilder to collect the bytes ' and create a string. Dim sBuilder As New System.Text.StringBuilder() ' Loop through each byte of the hashed data ' and format each one as a hexadecimal string. Dim idx As Integer For idx = 0 To data.Length - 1 sBuilder.Append(data(idx).ToString("x2")) Next idx Return sBuilder.ToString End Function
To use it, is fairly simple... NOTE: the messageboxes in the CheckDate function were for testing... you could change CheckDate to return the number of days left, or leave it as is...
Here's how I tested it... add a button to a form (strictly for testing... in reality your main sub or the form_load event - or the from constructor - would call checkDate) and add this to the click event:
vb Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim aCount As Integer = 0 Dim loopIt As Boolean = True 'My.Settings.Reset() 'This is here for design time support... otherwise you won't get your app to run agin Do While loopIt MessageBox.Show(String.Format("Checking Date: {0}.", Date.Now.AddDays(aCount))) loopIt = CheckDate(Date.Now.AddDays(aCount)) If Not loopIt Then MessageBox.Show("Trial Period Ended! Application closing!") Me.Close() Else MessageBox.Show("You can keep using the app") End If aCount += 1 Loop End Sub
Like I said, it's not perfect, I'll provide minimal support for it, in that I'll help you get it going if you want it, but other than that, you're on your own. Ff some one wants to take it and run with it and do something worthwhile with it, or even beef it up some... go right ahead... just let me know, as it would be interesting to see what could be done with it. Or better yet, add the modifications to this thread.
-tg

