{"id":55001126,"date":"2018-04-01T00:00:00","date_gmt":"2020-05-13T21:19:07","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1126"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Software_freischalten_per_Schluessel","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/","title":{"rendered":"Software freischalten per Schl&uuml;ssel"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Wenn Sie eine Software weitergeben, wollen Sie nat&uuml;rlich sicherstellen, dass diese nur von Kunden genutzt wird, die auch f&uuml;r die Software bezahlt haben. Wie k&ouml;nnen Sie das sicherstellen Eine M&ouml;glichkeit ist es, in Abh&auml;ngigkeit von einem Benutzernamen einen Freischaltungsschl&uuml;ssel zu erzeugen, den der Benutzer in die Anwendung eingeben muss, damit diese funktioniert. Auf diese Weise sorgen Sie nicht nur daf&uuml;r, dass der Benutzer diesen Schl&uuml;ssel erwerben muss, wenn er die Anwendung nutzen will. Damit ist gleichzeitig sichergestellt, dass Sie &#8211; wenn ein Benutzer die Anwendung weitergibt oder diese sogar in einem Portal zum Download bereitstellt &#8211; herausfinden, welcher Kunde die Software weitergegeben hat. Dieser Beitrag liefert die technischen Grundlagen f&uuml;r den Schutz einer Software mit Freischaltungsschl&uuml;ssel.<\/b><\/p>\n<h2>Voraussetzung<\/h2>\n<p>Voraussetzung f&uuml;r den Schutz der Software mit einem Freischaltungsschl&uuml;ssel ist nat&uuml;rlich, dass Sie diese nur als <b>.mde<\/b>&#8211; oder <b>.accde<\/b>-Datei weitergeben. Anderenfalls kann der Benutzer ja einfach in den Code schauen und die Schutzma&szlig;nahme aushebeln.<\/p>\n<h2>Startformular<\/h2>\n<p>Die Abfrage der Daten f&uuml;r die Freischaltung, also der E-Mail-Adresse und des Freischaltungsschl&uuml;ssels, soll in einem Startformular erfolgen. Dieses hei&szlig;t <b>frmStart <\/b>und sieht wie in Bild 1 aus. F&uuml;r das Formular stellen wir die Eigenschaften <b>Bildlaufleisten<\/b>, <b>Navigationsschaltfl&auml;chen<\/b>, <b>Datensatzmarkierer <\/b>und <b>Trennlinien <\/b>auf <b>Nein <\/b>und <b>Automatisch zentrieren <\/b>auf <b>Ja <\/b>ein. Au&szlig;erdem soll das Formular als Popup ge&ouml;ffnet werden, also so, dass der Benutzer keine weiteren Aktionen ausf&uuml;hren kann, wenn dieses Formular nicht geschlossen wurde. Dazu stellen wir die Eigenschaft <b>Popup <\/b>auf <b>Ja <\/b>ein.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_001.png\" alt=\"Formular zum Freischalten der Anwendung\" width=\"499,6607\" height=\"254,5981\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Formular zum Freischalten der Anwendung<\/span><\/b><\/p>\n<p>Um die vom Benutzer in die beiden Textfelder <b>txtEMail <\/b>und <b>txtSchluessel <\/b>eingegebenen Daten zu speichern, arbeiten wir mit einer Tabelle namens <b>tblOptionen<\/b>. Diese ist wie in Bild 2 aufgebaut und enth&auml;lt die drei Felder <b>ID<\/b>, <b>EMail <\/b>und <b>Schluessel<\/b>. Im Auflieferungszustand soll die Tabelle einen leeren Datensatz enthalten.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_002.png\" alt=\"Tabelle zum Speichern der Freischaltungsdaten\" width=\"499,6607\" height=\"359,1586\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Tabelle zum Speichern der Freischaltungsdaten<\/span><\/b><\/p>\n<p>Damit der Benutzer die Daten &uuml;ber das Formular <b>frmStart <\/b>eingeben kann, binden wir das Formular ausnahmsweise nicht &uuml;ber die Eigenschaft <b>Datenherkunft <\/b>an die Tabelle <b>tblOptionen<\/b>. Wir wollen die eingegebenen Daten ja nur dann speichern, wenn der Benutzer ein passendes Paar von E-Mail und Schl&uuml;ssel eingegeben hat. In diesem Fall soll das Formular <b>frmStart <\/b>gar nicht mehr erscheinen, sondern direkt das erste Formular der Anwendung angezeigt werden.<\/p>\n<h2>Startformular einrichten<\/h2>\n<p>Damit das Formular <b>frmStart<\/b> direkt beim &ouml;ffnen der Anwendung angezeigt wird, stellen wir in den Access-Optionen, die Sie &uuml;ber den Eintrag <b>Optionen <\/b>unter dem Ribbon-Tab <b>Datei <\/b>&ouml;ffnen, im Bereich <b>Aktuelle Datenbank <\/b>unter <b>Anwendungsoptionen <\/b>die Eigenschaft <b>Formular anzeigen <\/b>auf das Formular <b>frmStart <\/b>ein (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_003.png\" alt=\"Einstellen des Formulars frmStart als Startformular\" width=\"649,559\" height=\"434,1788\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Einstellen des Formulars frmStart als Startformular<\/span><\/b><\/p>\n<p>Wenn wir die Anwendung nun neu starten, um das Formular <b>frmStart <\/b>direkt beim Start anzuzeigen, gelingt das auf den ersten Blick wie gew&uuml;nscht. Allerdings kann man trotz des Modus als Popup noch direkt auf die Elemente des Navigationsbereichs oder des Ribbons zugreifen. Um dies zu verhindern, m&uuml;ssen wir auch noch die Eigenschaft <b>Modal <\/b>auf <b>True <\/b>einstellen. Dies gelingt allerdings nicht &uuml;ber das Eigenschaftsfenster, sodass wir die entsprechende Zuweisung in einer Prozedur unterbringen, die durch das Ereignis <b>Beim Laden <\/b>des Formulars ausgel&ouml;st wird. Diese Prozedur sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     Me.Modal = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Nun zeigt das Formular allerdings immer noch die Titelleiste sowie die Schaltfl&auml;chen zum Schlie&szlig;en, Minimieren und Maximieren an (siehe Bild 4). Dies &auml;ndern wir noch, indem wir die Eigenschaft <b>Rahmenart <\/b>auf <b>Keine <\/b>einstellen. Dadurch erscheint das Formular etwa unter Access 2016, wo der Hintergrund wei&szlig; ist, wie in Bild 5. Das sind jedoch Spielereien &#8211; wichtig ist, dass der Benutzer nicht um den Aufruf dieses Formulars herumkommt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_005.png\" alt=\"Anzeige des Startformulars\" width=\"649,559\" height=\"424,5385\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Anzeige des Startformulars<\/span><\/b><\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_004.png\" alt=\"Formular als Popup &ouml;ffnen\" width=\"424,7115\" height=\"255,061\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Formular als Popup &ouml;ffnen<\/span><\/b><\/p>\n<p>&uuml;brigens: Wenn Sie das Formular auf diese Art ge&ouml;ffnet haben, k&ouml;nnen Sie es nicht &uuml;ber die herk&ouml;mmlichen Elemente der Benutzeroberfl&auml;che wieder schlie&szlig;en &#8211; auch nicht mit der Tastenkombination <b>Strg + F4 <\/b>oder durch einen Wechsel in die Entwurfsansicht mit der Tastenkombination <b>Strg + Komma <\/b>(<b>,<\/b>).<\/p>\n<p>Allerdings f&uuml;hrt der Versuch, die Anwendung mit <b>Alt + F4 <\/b>zu schlie&szlig;en, zun&auml;chst zum Schlie&szlig;en des Formulars und dann bei erneuter Bet&auml;tigung zum Schlie&szlig;en der Anwendung. Diesen Weg m&uuml;ssten wir also noch blockieren. Dazu hinterlegen wir eine Prozedur f&uuml;r die Ereignis-eigenschaft <b>Bei Taste ab <\/b>des Formulars selbst, die wir wie folgt f&uuml;llen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_KeyDown(KeyCode<span style=\"color:blue;\"> As Integer<\/span>,  Shift<span style=\"color:blue;\"> As Integer<\/span>)\r\n     Select Case KeyCode\r\n         <span style=\"color:blue;\">Case <\/span>115\r\n             Select Case Shift\r\n                 <span style=\"color:blue;\">Case <\/span>acAltMask\r\n                     KeyCode = 0\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Damit diese Prozedur auch dann feuert, wenn eines der Steuerelemente des Formulars den Fokus hat, stellen wir noch die Eigenschaft <b>Tastenvorschau <\/b>auf <b>Ja <\/b>ein.<\/p>\n<p>Wie k&ouml;nnen wir das Formular aber nun beim Entwickeln noch schlie&szlig;en, ohne direkt die komplette Anwendung schlie&szlig;en zu m&uuml;ssen Der einzige Weg, der &uuml;brig bleibt, ist der &uuml;ber den Direktbereich des VBA-Fensters. Diesen rufen Sie mit der Tastenkombination <b>Strg + G <\/b>auf und geben dort die folgende Anweisung ein:<\/p>\n<pre>DoCmd.Close acForm, \"frmStart\"<\/pre>\n<h2>Eingabe des Freigabeschl&uuml;ssels<\/h2>\n<p>Damit kommen wir zum Freigabeschl&uuml;ssel selbst. Diesen soll der Benutzer neben der E-Mail-Adresse in das entsprechende Textfeld eingeben. Dann soll er den Schl&uuml;ssel durch Bet&auml;tigen der <b>OK<\/b>-Schaltfl&auml;che best&auml;tigen. Ist die Kombination aus E-Mail und Freigabeschl&uuml;ssel korrekt, sollen die beiden Informationen in der Tabelle <b>tblOptionen <\/b>gespeichert werden. Beim n&auml;chsten Aufruf der Anwendung sollen diese beiden Werte dann beim Aufruf des Formulars <b>frmStart <\/b>gepr&uuml;ft werden. Passen diese zusammen, setzt die Anwendung den Startvorgang fort und zeigt das gew&uuml;nschte Element der Benutzeroberfl&auml;che an. Anderenfalls wird der Benutzer gebeten, die korrekten Daten zur Freischaltung anzugeben.<\/p>\n<p>Nachfolgend schauen wir uns mehrere Varianten an, wie wir die E-Mail-Adresse und den Schl&uuml;ssel erstellen und pr&uuml;fen k&ouml;nnen. Die erste Variante ist die zeitlich unbegrenzte, die zweite ist eine, mit der Sie eine Software befristet bis zu einem bestimmten Datum freischalten lassen k&ouml;nnen.<\/p>\n<h2>Einfache Variante: E-Mail und Schl&uuml;ssel m&uuml;ssen passen<\/h2>\n<p>Um die Schl&uuml;ssel zu generieren, verwenden wir eine Klasse namens <b>clsCrypt <\/b>des Autors Tim Braun (siehe Modul im VBA-Projekt). Diese bietet vor allen die f&uuml;r uns interessante Funktion namens <b>GetSHA1 <\/b>an, die eine als Parameter &uuml;bergebene Zeichenkette in einen Schl&uuml;ssel umwandelt.<\/p>\n<p>Diese Funktion k&ouml;nnen wir nach der Initialisierung eines Objekts auf Basis der Klasse <b>clsCrypt<\/b> wie in der folgenden Prozedur testen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_GetSHA1()\r\n     <span style=\"color:blue;\">Dim <\/span>objCrypt<span style=\"color:blue;\"> As <\/span>clsCrypt\r\n     <span style=\"color:blue;\">Set<\/span> objCrypt = <span style=\"color:blue;\">New<\/span> clsCrypt\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objCrypt.GetSHA1(\"Andr&eacute; Minhorst\")\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis lautet dann:<\/p>\n<pre>B431123435AE6C58E661FBCA736FAEF739BE6F2F<\/pre>\n<p>Der Benutzer wird Probleme haben, daraus zu ermitteln, auf welche Weise der Schl&uuml;ssel produziert wird. Es sollte nat&uuml;rlich nicht allzu einfach sein &#8211; wenn Sie also einfach nur die E-Mail-Adresse verschl&uuml;sseln und als Schl&uuml;ssel zum Freischalten der Anwendung nutzen, besteht die Gefahr, dass der Benutzer sich seine eigenen Schl&uuml;ssel erstellt.<\/p>\n<p>Zum Erstellen eines einfachen Schl&uuml;ssels verwenden wir nun die E-Mail-Adresse und h&auml;ngen eine einfache Zeichenfolge wie etwa <b>xxx <\/b>an (diese darf nat&uuml;rlich ebenfalls etwas komplizierter ausfallen). Der zu kodierende Ausdruck hei&szlig;t dann im Falle meiner eigenen E-Mail-Adresse etwa so: <b>andre@minhorst.comxxx<\/b><\/p>\n<p>Der verschl&uuml;sselte Ausdruck hei&szlig;t dann:<\/p>\n<pre>D382469636E463CE93079D0F9714212EFC4D54A6<\/pre>\n<p>Wir wollen uns eine kleine Funktion bauen, um die Schl&uuml;ssel einfacher herstellen zu k&ouml;nnen. Diese sieht so aus:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Verschluesseln(strAusdruck<span style=\"color:blue;\"> As String<\/span>) <span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objCrypt<span style=\"color:blue;\"> As <\/span>clsCrypt\r\n     <span style=\"color:blue;\">Dim <\/span>strVerschluesselt<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCrypt = <span style=\"color:blue;\">New<\/span> clsCrypt\r\n     strVerschluesselt = objCrypt.GetSHA1(strAusdruck)\r\n     Verschluesseln = strVerschluesselt\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Im Direktfenster setzen Sie die Funktion wie folgt ein:<\/p>\n<pre>  Verschluesseln(\"andre@minhorst.comxxx\")\r\nD382469636E463CE93079D0F9714212EFC4D54A6<\/pre>\n<h2>Eingabe des Schl&uuml;ssels<\/h2>\n<p>Nun, wo wir eine Methode zum Erzeugen der Schl&uuml;ssel programmiert haben, wollen wir uns um das Formular zur Eingabe der E-Mail-Adresse und des Schl&uuml;ssels k&uuml;mmern. Dazu f&uuml;gen wir der Schaltfl&auml;che <b>cmdOK <\/b>den Code aus Listing 1 hinzu.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdOK_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     strEMail = Me!txtEMail\r\n     strSchluessel = Me!txtSchluessel\r\n     <span style=\"color:blue;\">If <\/span>Verschluesseln(strEMail & \"xxx\") = strSchluessel<span style=\"color:blue;\"> Then<\/span>\r\n         SchluesselSchreiben strEMail, strSchluessel\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Anwendung wurde erfolgreich freigeschaltet.\"\r\n         DoCmd.Close acForm, Me.Name\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"E-Mail-Adresse und\/oder Schl&uuml;ssel sind nicht korrekt.\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Pr&uuml;fung des Schl&uuml;ssels<\/span><\/b><\/p>\n<p>Die Ereignisprozedur <b>cmdOK_Click <\/b>tr&auml;gt die Werte der beiden Textfelder <b>txtEMail <\/b>und <b>txtSchluessel <\/b>in die beiden Variablen <b>strEMail <\/b>und <b>strSchluessel <\/b>ein. Dann pr&uuml;ft sie in einer <b>If&#8230;Then<\/b>-Bedingung, ob der verschl&uuml;sselte Wert der E-Mails-Adresse plus der angeh&auml;ngten Zeichenkette xxx mit der vom Benutzer eingegebenen Schl&uuml;ssel-Zeichenfolge &uuml;bereinstimmt. Ist dies der Fall, ruft die Prozedur die Funktion <b>SchluesselSchreiben <\/b>auf und &uuml;bergibt die E-Mail und den Schl&uuml;ssel an diese Funktion. Es erscheint eine Meldung, welche die erfolgreiche Freischaltung best&auml;tigt und das Formular wird geschlossen.<\/p>\n<p>Hat der Benutzer nicht die richtige Kombination aus E-Mail-Adresse und Schl&uuml;ssel eingegeben, erscheint ebenfalls eine Meldung und das Start-Formular bleibt ge&ouml;ffnet. Er kann es nun erneut probieren oder aber mit einem Klick auf die Schaltfl&auml;che <b>cmdBeenden <\/b>die Anwendung schlie&szlig;en.<\/p>\n<h2>Schreiben von E-Mail und Schl&uuml;ssel<\/h2>\n<p>Die von der oben beschriebenen Prozedur aufgerufene Funktion <b>SchluesselSchreiben<\/b> erwartet die E-Mail-Adresse sowie den Schl&uuml;ssel als Parameter (siehe Listing 2). Die Funktion pr&uuml;ft, ob sich bereits ein Datensatz in der Tabelle <b>tblOptionen <\/b>befindet. Falls nicht, f&uuml;gt sie einen neuen Datensatz hinzu und tr&auml;gt die beiden Werte aus den Parametern <b>strEMail <\/b>und <b>strSchluessel <\/b>in die beiden Felder der Tabelle ein. Ist bereits ein Datensatz vorhanden, werden die Inhalte der beiden Felder durch die neuen Werte ersetzt.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>SchluesselSchreiben(strEMail<span style=\"color:blue;\"> As String<\/span>, strSchluessel<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblOptionen\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">If <\/span>rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         rst.Add<span style=\"color:blue;\">New<\/span>\r\n         rst!EMail = strEMail\r\n         rst!Schluessel = strSchluessel\r\n         rst.Update\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         rst.Edit\r\n         rst!EMail = strEMail\r\n         rst!Schluessel = strSchluessel\r\n         rst.Update\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Schreiben des Schl&uuml;ssels<\/span><\/b><\/p>\n<p>Die Tabelle sieht danach etwa wie in Bild 6 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_006.png\" alt=\"Tabelle mit den Freischaltungsdaten\" width=\"499,6607\" height=\"165,9682\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Tabelle mit den Freischaltungsdaten<\/span><\/b><\/p>\n<h2>Inhalt der Tabelle beim &ouml;ffnen pr&uuml;fen<\/h2>\n<p>Nun haben wir allerdings nur den Fall abgedeckt, dass der Benutzer die Anwendung zum ersten Mal &ouml;ffnet. Wenn er nun eine g&uuml;ltige Kombination aus E-Mail-Adresse und Schl&uuml;ssel angegeben hat, soll er ja nicht bei jedem erneuten &ouml;ffnen der Anwendung erneut die Daten eingeben m&uuml;ssen. Also wollen wir die Prozedur <b>cmdOK_Click <\/b>so erweitern, dass diese zun&auml;chst pr&uuml;ft, ob bereits g&uuml;ltige Daten in der Tabelle <b>tblOptionen <\/b>vorliegen.<\/p>\n<p>Dazu f&uuml;gen wir der Ereignisprozedur, die durch das Ereignis <b>Beim &ouml;ffnen <\/b>ausgel&ouml;st wird, die folgenden Anweisungen hinzu:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Open(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">If <\/span>SchluesselPruefen = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         Cancel = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wenn die Funktion <b>SchluesselPruefen <\/b>den Wert True zur&uuml;ckliefert, stellt die Prozedur den Wert des Parameters <b>Cancel <\/b>auf <b>True <\/b>ein. Dies f&uuml;hrt dazu, dass das Formular <b>frmStart <\/b>direkt wieder geschlossen wird.<\/p>\n<p>Es fehlt nun noch die Funktion <b>SchluesselPruefen<\/b>. Diese Funktion finden Sie in Listing 3. Die Funktion erwartet keine Parameter, da sie die zu pr&uuml;fenden Werte direkt aus der Tabelle <b>tblOptionen <\/b>einliest. Auch hier kann es wieder sein, dass noch gar kein Datensatz in der Tabelle gespeichert ist. Dies pr&uuml;ft die Prozedur gleich in der ersten <b>If&#8230;Then<\/b>-Bedingung mit dem Ausdruck <b>rst.EOF<\/b>. Liefert dies <b>True<\/b>, enth&auml;lt die Tabelle noch keinen Datensatz. In diesem Fall soll die Funktion den Wert <b>False <\/b>zur&uuml;ckliefern.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>SchluesselPruefen()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolSchluesselPruefen <span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblOptionen\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         strEMail = rst!EMail\r\n         strSchluessel = rst!Schluessel\r\n         <span style=\"color:blue;\">If <\/span>Verschluesseln(strEMail & \"xxx\") = strSchluessel<span style=\"color:blue;\"> Then<\/span>\r\n             bolSchluesselPruefen = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             bolSchluesselPruefen = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         bolSchluesselPruefen = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     SchluesselPruefen = bolSchluesselPruefen\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Pr&uuml;fen, ob der in der Tabelle tblOptionen gespeicherte Schl&uuml;ssel korrekt ist<\/span><\/b><\/p>\n<p>Ist hingegen bereits ein Datensatz vorhanden, liest die Prozedur die beiden Werte der Felder <b>EMail <\/b>und <b>Schluessel <\/b>in die Variablen <b>strEMail <\/b>und <b>strSchluessel <\/b>ein.<\/p>\n<p>In einer weiteren <b>If&#8230;Then<\/b>-Bedingung pr&uuml;ft die Funktion dann, ob der mit der Funktion <b>Verschluesseln <\/b>verschl&uuml;sselte Ausdruck aus der E-Mail-Adresse und der Zeichenkette <b>xxx <\/b>dem Schl&uuml;ssel aus <b>strSchluessel <\/b>entspricht. Ist dies der Fall, erh&auml;lt die Variable <b>bolSchluesselPruefen <\/b>den Wert <b>True<\/b>, anderenfalls den Wert <b>False<\/b>.<\/p>\n<p>Wenn der Benutzer nun einmalig die richtige Kombination aus E-Mail-Adresse und Schl&uuml;ssel eingegeben hat, wird das Formular <b>frmStart <\/b>erst gar nicht ge&ouml;ffnet &#8211; der Vorgang endet bereits in der Prozedur, die durch das Ereignis <b>Beim &ouml;ffnen <\/b>ausgel&ouml;st wird.<\/p>\n<h2>Weitere Bedingung mit dem Schl&uuml;ssel &uuml;bergeben<\/h2>\n<p>Dies war die einfachste Variante f&uuml;r das Freischalten der Software durch die Angabe einer E-Mail-Adresse und einen Schl&uuml;ssel. Es kann aber sein, dass Sie weitergehende Anforderungen haben, die &uuml;ber die Angabe von E-Mail-Adresse und Registrierungsschl&uuml;ssel &uuml;bermittelt werden.<\/p>\n<p>Zum Beispiel k&ouml;nnte es sein, dass die Anwendung verschiedene Funktionen bereitstellt, von denen je nach erworbener Lizenz nur eine oder mehrere Funktionen freigeschaltet sein sollen. Wir wollen dies im Folgenden so nachbilden, dass im Anschluss an das Formular <b>frmStart <\/b>das Formular <b>frmAnwendung<\/b> ge&ouml;ffnet wird, von dem abh&auml;ngig vom vorliegenden Schl&uuml;ssel eine oder mehrere Schaltfl&auml;chen aktiviert oder auch nicht aktiviert sind.<\/p>\n<p>Das Formular <b>frmStart <\/b>soll also grunds&auml;tzlich direkt wieder verschwinden, wenn der Benutzer einen der g&uuml;ltigen Schl&uuml;ssel erhalten hat.<\/p>\n<p>Die einzelnen Funktionen wollen wir durch verschiedene Zus&auml;tze codieren, die wir in Form einer Zahl an die E-Mail-Adresse und die Zeichenfolge <b>xxx <\/b>anh&auml;ngen. Wir wollen drei Funktionen vereinbaren, die wir in einer bin&auml;ren Zahl als nutzbar oder nicht nutzbar kodieren. Wenn alle drei Funktionen verf&uuml;gbar sind, soll die bin&auml;re Zahl also <b>111 <\/b>lauten und als <b>7 <\/b>an die zu verschl&uuml;sselnde Zeichenfolge angeh&auml;ngt werden. Wenn nur die letzte Funktion verf&uuml;gbar sein soll, verwenden wir den Code <b>001<\/b>, also <b>1<\/b>, wenn nur die erste Funktion verf&uuml;gbar ist, den Code <b>100<\/b>, also <b>4<\/b>.<\/p>\n<p>Achtung: Diese Version der L&ouml;sung finden Sie unter dem Dateinamen <b>Freischaltungsschluessel_II.accdb<\/b>.<\/p>\n<p>Die Funktion <b>VerschluesselnMitFunktion<\/b>, die wir ausschlie&szlig;lich zum Erstellen der Schl&uuml;ssel verwenden, erwartet neben der Angabe der E-Mail-Adresse noch drei <b>Boolean<\/b>-Werte f&uuml;r die Parameter <b>bolFunktion1<\/b>, <b>bolFunktion2 <\/b>und <b>bolFunktion3<\/b>, die angeben, ob die Funktionen 1, 2 oder 3 freigeschaltet werden sollen (siehe Listing 4). Die drei Boolean-Variablen werden mit den Werten <b>-4<\/b>, <b>-2<\/b> oder <b>-1<\/b> multipliziert und addiert. Da die Boolean-Parameter im Falle von <b>True <\/b>den Wert <b>-1<\/b> aufweisen, erhalten wir auf diese Weise Werte von <b>0 <\/b>bis <b>7 <\/b>f&uuml;r diese Berechnung. Der Rest der Funktion funktioniert wie die bisher bekannte Variante, f&uuml;gt allerdings auch die Zeichenkette <b>xxx <\/b>noch automatisch hinzu.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>VerschluesselnMitFunktion(strMail<span style=\"color:blue;\"> As String<\/span>, bolFunktion1<span style=\"color:blue;\"> As Boolean<\/span>, bolFunktion2<span style=\"color:blue;\"> As Boolean<\/span>, _\r\n         bolFunktion3<span style=\"color:blue;\"> As Boolean<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objCrypt<span style=\"color:blue;\"> As <\/span>clsCrypt\r\n     <span style=\"color:blue;\">Dim <\/span>strVerschluesselt<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strAusdruck<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCrypt = <span style=\"color:blue;\">New<\/span> clsCrypt\r\n     strAusdruck = strMail & \"xxx\" & bolFunktion1 * -4 + bolFunktion2 * -2 + bolFunktion3 * -1\r\n     <span style=\"color:blue;\">Debug.Print<\/span> strAusdruck\r\n     strVerschluesselt = objCrypt.GetSHA1(strAusdruck)\r\n     Verschluesseln = strVerschluesselt\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Neue Version der Funktion Verschluesseln namens VerschluesselnMItFunktion, die weitere Eigenschaften ber&uuml;cksichtigt<\/span><\/b><\/p>\n<p>Dadurch ergibt sich auch eine neue Version der Ereignisprozedur, die durch die Schaltfl&auml;che <b>cmdOK<\/b> ausgel&ouml;st wird. Diese sieht wie in Listing 5 aus und enth&auml;lt eine zus&auml;tzliche Variable namens <b>i<\/b>. Diese dient als Variable in einer <b>For&#8230;Next<\/b>-Schleife, die alle Zahlen von 0 bis 7 durchl&auml;uft &#8211; also alle Werte, die f&uuml;r die verschiedenen Kombinationen der freigeschalteten Funktionen der Anwendung vorkommen k&ouml;nnen. Innerhalb der Schleife haben wir eine <b>If&#8230;Then<\/b>-Bedingung, die pr&uuml;ft, ob der verschl&uuml;sselte Wert der E-Mail plus der Zeichenkette <b>xxx<\/b> plus dem aktuellen Wert von <b>i<\/b> dem vom Benutzer angegebenen Wert des Schl&uuml;ssels entspricht. Falls ja, ruft die Routine wiederum die Prozedur <b>SchluesselSchreiben <\/b>auf und &uuml;bergibt die E-Mail-Adresse und den Schl&uuml;ssel.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdOK_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     strEMail = Me!txtEMail\r\n     strSchluessel = Me!txtSchluessel\r\n     For i = 0 To 7\r\n         <span style=\"color:blue;\">If <\/span>Verschluesseln(strEMail & \"xxx\" & i) = strSchluessel<span style=\"color:blue;\"> Then<\/span>\r\n             SchluesselSchreiben strEMail, strSchluessel\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Die Anwendung wurde erfolgreich freigeschaltet.\"\r\n             DoCmd.Close acForm, Me.Name\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     <span style=\"color:blue;\">MsgBox<\/span> \"E-Mail-Adresse und\/oder Schl&uuml;ssel sind nicht korrekt.\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Neue Version der Ereignisprozedur, die durch die Schaltfl&auml;che cmdOK ausgel&ouml;st wird.<\/span><\/b><\/p>\n<p>Es fehlt noch die Funktion <b>SchluesselPruefen<\/b>, die ebenfalls um die Schleife erweitert werden muss (siehe Listing 6). Diese nutzt nach der Ermittlung von E-Mail-Adresse und Schl&uuml;ssel aus der Tabelle <b>tblOptionen <\/b>wiederum eine <b>For&#8230;Next<\/b>-Schleife, die alle Zahlen von <b>0 <\/b>bis <b>7 <\/b>durchl&auml;uft und mit der Funktion <b>Verschluesseln<\/b> testet, ob der Wert aus <b>strSchluessel <\/b>einem der acht durchlaufenen verschl&uuml;sselten Werte entspricht.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>SchluesselPruefen()<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolSchluesselPruefen <span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblOptionen\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         strEMail = rst!EMail\r\n         strSchluessel = rst!Schluessel\r\n         For i = 0 To 7\r\n             <span style=\"color:blue;\">If <\/span>Verschluesseln(strEMail & \"xxx\" & i) = strSchluessel<span style=\"color:blue;\"> Then<\/span>\r\n                 bolSchluesselPruefen = <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">Exit For<\/span>\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 bolSchluesselPruefen = <span style=\"color:blue;\">False<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> i\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         bolSchluesselPruefen = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     SchluesselPruefen = i\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Neue Version der Funktion SchluesselPruefen<\/span><\/b><\/p>\n<p>Der neuen Version der Methode <b>Form_Open<\/b>, welche beim &ouml;ffnen des Formulars das Vorhandensein eines g&uuml;ltigen Schl&uuml;ssels pr&uuml;ft, f&uuml;gen wir eine <b>MsgBox<\/b>-Anweisung hinzu, welche den gefundenen Wert von <b>i<\/b> ausgibt. Auf diese Weise erfahren wir auch gleich, welcher Funktionsumfang f&uuml;r den aktuellen Schl&uuml;ssel freigeschaltet wurde. Den Wert speichert die Prozedur in der Variablen <b>intFunktionen<\/b>. Ist der Wert gr&ouml;&szlig;er <b>0<\/b>, ruft die Prozedur au&szlig;erdem das Formular <b>frmAnwendung <\/b>auf und &uuml;bergibt den Wert von <b>intFunktionen <\/b>als &ouml;ffnungsparameter. Die neue Version der Prozedur sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Open(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>intFunktionen<span style=\"color:blue;\"> As Integer<\/span>\r\n     intFunktionen = SchluesselPruefen\r\n     <span style=\"color:blue;\">If <\/span>intFunktionen &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Funktionsumfang: \" & intFunktionen\r\n        DoCmd.OpenForm \"frmAnwendung\", _\r\n            OpenArgs:=intFunktionen\r\n         Cancel = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Praktisches Beispiel f&uuml;r die Aktivierung von Funktionen<\/h2>\n<p>Nun wissen wir, dass der Wert <b>7 <\/b>f&uuml;r <b>intFunktionen <\/b>alle drei Funktionen freischaltet, <b>4 <\/b>schaltet nur die dritte Funktion frei, <b>1 <\/b>nur die erste oder <b>5 <\/b>die erste und die dritte.<\/p>\n<p>Wie aber k&ouml;nnen wir dies umsetzen, wenn es tats&auml;chlich daran geht, bestimmte Funktionen ein- oder auszuschalten Wir zeigen dies anhand eines Formulars, das drei Schaltfl&auml;chen zum Ausf&uuml;hren der drei genannten Funktionen enth&auml;lt und das im Entwurf wie in Bild 7 aussieht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_007.png\" alt=\"Formular mit Beispielfunktionsaufrufen\" width=\"499,6607\" height=\"252,228\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Formular mit Beispielfunktionsaufrufen<\/span><\/b><\/p>\n<p>F&uuml;r das Ereignis <b>Beim Laden <\/b>des Formulars hinterlegen wir nun die folgende Ereignisprozedur:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Dim <\/span>intFunktionen<span style=\"color:blue;\"> As Integer<\/span>\r\n     intFunktionen = Me.OpenArgs\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (intFunktionen And 1) = 1<span style=\"color:blue;\"> Then<\/span>\r\n         Me!cmdFunktion1.Enabled = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (intFunktionen And 2) = 2<span style=\"color:blue;\"> Then<\/span>\r\n         Me!cmdFunktion2.Enabled = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (intFunktionen And 4) = 4<span style=\"color:blue;\"> Then<\/span>\r\n         Me!cmdFunktion3.Enabled = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese schreibt zun&auml;chst den vom aufrufenden Formular <b>frmStart <\/b>&uuml;bergebenen Wert aus dem &ouml;ffnungsargument in die Variable <b>intFunktionen<\/b>. Dann nutzt sie den bin&auml;ren Vergleich mit dem <b>And<\/b>-Operator, um zu pr&uuml;fen, ob der Wert <b>1<\/b>, <b>2 <\/b>oder <b>4 <\/b>in dem in <b>intFunktionen <\/b>enthaltenen Wert enthalten sind. In unserem Fall lautete der Wert <b>4<\/b>, was das Ergebnis aus Bild 8 lieferte.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_008.png\" alt=\"Formular mit einer freigeschalteten Funktion\" width=\"499,6607\" height=\"211,1661\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Formular mit einer freigeschalteten Funktion<\/span><\/b><\/p>\n<p>Den Wert von <b>intFunktionen<\/b> k&ouml;nnen Sie auch in einer globalen Variablen oder in einer <b>TempVar <\/b>speichern und dann von allen Stellen, an denen gepr&uuml;ft werden soll, ob eine Funktion freigeschaltet ist, abrufen. Damit lassen sich beispielsweise auch Ribbon-Schaltfl&auml;chen aktivieren oder deaktivieren (mehr dazu im Beitrag <b>Ribbon-Elemente aktivieren und deaktivieren<\/b>, <b>www.access-im-unternehmen.de\/1122<\/b>).<\/p>\n<h2>Zeitliche Limitierung der Freischaltung<\/h2>\n<p>Kommen wir zur letzten Aufgabe &#8211; der zeitlichen Limitierung der durch einen Freischaltschl&uuml;ssel freigeschalteten Funktionen. Sie k&ouml;nnen beispielsweise eine zeitlich begrenzte Version einer Software herausgeben, damit der Benutzer diese etwa f&uuml;r einen Monat testen kann. Oder Sie verkaufen dem Benutzer nur eine zeitlich limitierte Lizenz f&uuml;r ein Programm, das einen neuen Registrierungsschl&uuml;ssel ben&ouml;tigt, wenn der Nutzungszeitraum abgelaufen ist.<\/p>\n<p>Dazu schauen wir uns zwei Varianten an:<\/p>\n<ul>\n<li>Die erste speichert einfach das Datum, an dem die Software freigeschaltet wurde, an einer versteckten Stelle wie beispielsweise im Beitrag <b>Daten in Properties verstecken <\/b>(<b>www.access-im-unternehmen.de\/1125<\/b>) beschrieben und pr&uuml;ft beim Start jeweils, ob die maximale Nutzungsdauer bereits &uuml;berschritten wurde. Oder Sie tragen direkt das Datum f&uuml;r das Ende der Nutzungsdauer an einer solchen Stelle ein und gleichen beim Start die Systemzeit mit der maximalen Nutzungsdauer ab. Diese Variante schauen wir uns nicht im Detail an.<\/li>\n<li>Bei der zweiten Variante steckt die maximale Nutzungsdauer in Form einer Datumsangabe im Freischaltungs-Schl&uuml;ssel f&uuml;r die Anwendung. Der Freischaltungsschl&uuml;ssel wird dann f&uuml;r alle zu &uuml;berpr&uuml;fenden Datumsangaben mit einem testweise erzeugten Schl&uuml;ssel verglichen, bis ein Treffer gefunden wurde &#8211; oder eben kein Treffer, was bedeutet, dass die Software nicht mehr genutzt werden darf. Dies sollte sich auf einen &uuml;berschaubaren Zeitraum konzentrieren, da die Erzeugung der Schl&uuml;ssel zum Vergleichen nat&uuml;rlich Rechenzeit beansprucht.<\/li>\n<\/ul>\n<p>Achtung: Die L&ouml;sung finden Sie in der Beispieldatenbank <b>Freischaltungsschluessel_III.accdb<\/b>.<\/p>\n<h2>Zeitliche Limitierung per Datumsvergleich<\/h2>\n<p>Die Vorgehensweise bei der zweiten Variante sieht also wie folgt aus:<\/p>\n<p>Wir erzeugen einen Schl&uuml;ssel, der die E-Mail-Adresse, den Funktionsumfang sowie das Ablaufdatum enth&auml;lt. Das Ablaufdatum sollte sich bei einer tageweisen Pr&uuml;fung im Rahmen eines Jahres bewegen, da der Rechenaufwand sonst zu hoch wird. Nehmen wir also an, wir haben den 12.3.2018 und wollen einen Freischaltschl&uuml;ssel f&uuml;r alle Funktionen erzeugen, der bis zum 12.4.2018 g&uuml;ltig ist. F&uuml;r die E-Mail-Adresse <b>andre@minhorst.com <\/b>lautet der zu verschl&uuml;sselnde Ausdruck also:<\/p>\n<pre>andre@minhorst.comxxx7_20190412<\/pre>\n<p>Der Schl&uuml;ssel hei&szlig;t dann:<\/p>\n<pre>A183F4A35AC6417BD5A4BD80600657A3195FEC0A<\/pre>\n<p>Die Prozedur aus Listing 7 zeigt, wie wir herausfinden, mit welchen Funktionen und bis zu welchem Datum die Anwendung freigeschaltet ist. Dazu durchl&auml;uft sie die m&ouml;glichen Funktionen von <b>1 <\/b>bis <b>7 <\/b>und die Datumsangaben vom heutigen Datum bis zum Datum in einem Jahr. Dies geschieht in zwei verschachtelten Schleifen. Die &auml;u&szlig;ere enth&auml;lt in der Variablen <b>i <\/b>die Funktion, die zweite in der Variablen <b>j <\/b>die Anzahl der Tage vom aktuellen Datum ausgehend. Die erste Anweisung innerhalb der inneren <b>For&#8230;Next<\/b>-Schleife stellt den zu pr&uuml;fenden Ausdruck zusammen, und zwar aus der E-Mail-Adresse, der Zeichenkette <b>xxx<\/b>, dem Wert f&uuml;r die Funktionen von <b>1 <\/b>bis <b>7<\/b>, einen Unterstrich und das Datum im Format <b>yyyymmdd<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>SchluesselPruefenBeispiel()\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>j<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strCode<span style=\"color:blue;\"> As String<\/span>\r\n     strMail = \"andre@minhorst.com\"\r\n     For i = 1 To 7\r\n         For j = 1 To 365\r\n             strCode = strMail & \"xxx\" & i & \"_\" & Format(Date + j, \"yyyymmdd\")\r\n             strSchluessel = Verschluesseln(strCode)\r\n             <span style=\"color:blue;\">If <\/span>strSchluessel = \"A183F4A35AC6417BD5A4BD80600657A3195FEC0A\"<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Funktionen: \" & i & \" Datum: \" & Date + j\r\n                 <span style=\"color:blue;\">Exit Sub<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> j\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Pr&uuml;fen, ob der Schl&uuml;ssel noch g&uuml;ltig ist<\/span><\/b><\/p>\n<p>Auf diese Weise stellt sie alle m&ouml;glichen Ausdr&uuml;cke zusammen, die dann in der folgenden Anweisung verschl&uuml;sselt und danach mit unserem vorliegenden Schl&uuml;ssel verglichen werden. Sobald hier eine &uuml;bereinstimmung vorliegt, k&ouml;nnen wir aufgrund der Werte von <b>i <\/b>und <b>j <\/b>ausgeben, welche Funktionen und bis zu welchem Datum die Anwendung noch freigeschaltet ist.<\/p>\n<p>Die aktuelle Version braucht nat&uuml;rlich eine Menge Zeit, da wir je nach aktuellem Datum und Ablaufdatum eine Menge Zeichenketten verschl&uuml;sseln m&uuml;ssen. F&uuml;r die aktuelle Version ben&ouml;tigen wir auf dem Testrechner beispielsweise mehr als sechs Sekunden. Auch Variationen, wo wir direkt mit dem Datum als Z&auml;hlervariable arbeiten oder wo wir das Format des Datums nicht in <b>yyymmdd <\/b>&auml;ndern, sondern das Standardzeitformat nutzen, f&uuml;hren nicht zu einer schnelleren Laufzeit. Und das ist definitiv zu lang, wenn diese Prozedur bei jedem Start der Anwendung durchgef&uuml;hrt werden soll.<\/p>\n<p>Also &uuml;berlegen wir uns eine Variante. Bei dieser soll das Enddatum immer auf einen Samstag fallen. Warum Weil wir dadurch nur noch ein Siebtel der Verschl&uuml;sselungsvorg&auml;nge durchf&uuml;hren m&uuml;ssen. Dazu erstellen wir die Funktion aus Listing 8. Diese nimmt nun auch gleich noch alle f&uuml;r die Untersuchung wichtigen Parameter an: den zu untersuchenden Schl&uuml;ssel und die E-Mail-Adresse. Die R&uuml;ckgabeparameter <b>datGueltigBis <\/b>und <b>intFunktionen <\/b>liefern das Datum und den Funktionsumfang, der sich aus dem zu untersuchenden Schl&uuml;ssel ergibt. Die Funktion ermittelt zun&auml;chst in einer Schleife das Datum des n&auml;chsten Samstags nach dem aktuellen Datum und tr&auml;gt dieses in die Variable <b>startDate <\/b>ein. Danach startet sie in die bereits bekannte <b>For&#8230;Next<\/b>-Schleife f&uuml;r die sieben Funktionen. Die zweite Schleife enth&auml;lt bereits eine wichtige &auml;nderung: Das Startdatum ist ja das Datum aus <b>startDate<\/b>, also der erste Samstag nach dem aktuellen Datum. Dieses wird nun nicht mehr in Einer-Schritten, sondern in Siebener-Schritten hochgez&auml;hlt (<b>Step 7<\/b>). Innerhalb der Schleife stellt die Prozedur in <b>strCode <\/b>den aktuellen Code zusammen, der dann verschl&uuml;sselt und in die Variable <b>strSchluesselTemp <\/b>geschrieben wird. Stimmt dieser schlie&szlig;lich mit dem Wert des Parameters <b>strSchluessel <\/b>&uuml;berein, werden die R&uuml;ckgabevariablen <b>intFunktionen <\/b>und <b>datGueltigBis <\/b>gef&uuml;llt und der Funktionswert auf <b>True <\/b>eingestellt sowie die Funktion mit <b>Exit Function <\/b>beendet.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SchluesselGueltig(strSchluessel<span style=\"color:blue;\"> As String<\/span>, strEMail<span style=\"color:blue;\"> As String<\/span>, _\r\n         datGueltigBis<span style=\"color:blue;\"> As Date<\/span>, intFunktionen<span style=\"color:blue;\"> As Integer<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>dat<span style=\"color:blue;\"> As Date<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>startDate<span style=\"color:blue;\"> As Date<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strCode<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluesselTemp<span style=\"color:blue;\"> As String<\/span>\r\n     startDate = Date\r\n     For i = 0 To 6\r\n         startDate = Date + i\r\n         <span style=\"color:blue;\">If <\/span>Weekday(startDate, vbSaturday) = 1<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Exit For<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     For i = 1 To 7\r\n         For dat = startDate To startDate + 365 Step 7\r\n             strCode = strEMail & \"xxx\" & i & \"_\" & dat\r\n             strSchluesselTemp = Verschluesseln(strCode)\r\n             <span style=\"color:blue;\">If <\/span>strSchluesselTemp = strSchluessel<span style=\"color:blue;\"> Then<\/span>\r\n                 intFunktionen = i\r\n                 datGueltigBis = dat\r\n                 SchluesselGueltig = <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">Exit Function<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> dat\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Pr&uuml;fen, ob der Schl&uuml;ssel noch g&uuml;ltig ist &#8211; erweiterte Fassung<\/span><\/b><\/p>\n<p>Ein Beispielaufruf f&uuml;r diese Funktion sieht etwa wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_SchluesselGueltig()\r\n     <span style=\"color:blue;\">Dim <\/span>datGueltigBis<span style=\"color:blue;\"> As Date<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intFunktionen<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     ''''f&uuml;r \"andre@minhorst.comxxx7_16.03.2019\"\r\n     strSchluessel = \"BE9F96C151C9D1CA97AF155D4B880E1BD8EDDE47\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> SchluesselGueltig(strSchluessel,  datGueltigBis, intFunktionen)\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"G&uuml;ltig bis: \" & datGueltigBis\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Funktionen: \" & intFunktionen\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>&auml;nderung des Freischaltungs-Schl&uuml;ssel<\/h2>\n<p>Wenn der Benutzer Funktionen zu einer bestehenden Anwendung hinzukauft, k&ouml;nnen Sie ihm einen neuen Freischaltungs-Schl&uuml;ssel erstellen und zusenden. Allerdings m&uuml;ssen wir in der Anwendung dann auch noch einen Ort vorsehen, an dem er den neuen Schl&uuml;ssel eingeben kann. Dazu haben wir einfach eine neue Schaltfl&auml;che zum Formular <b>frmAnwendung<\/b> hinzugef&uuml;gt, &uuml;ber die er das Formular <b>frmStart <\/b>erneut &ouml;ffnen kann (siehe Bild 9). Diese l&ouml;st die folgende Prozedur aus:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_1126_009.png\" alt=\"Schaltfl&auml;che zum erneuten Eingeben des Freischaltungs-Schl&uuml;ssels\" width=\"424,7115\" height=\"295,9846\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Schaltfl&auml;che zum erneuten Eingeben des Freischaltungs-Schl&uuml;ssels<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdFreischalten_Click()\r\n     DoCmd.Close acForm, Me.Name\r\n     DoCmd.OpenForm \"frmStart\", WindowMode:=acDialog, _\r\n         OpenArgs:=\"Freischalten\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wir nutzen also einfach erneut das Formular <b>frmStart <\/b>und &uuml;bergeben diesmal beim &ouml;ffnen mit dem &ouml;ffnungsargument die Zeichenkette <b>Freischalten<\/b>. Im Formular <b>frmStart<\/b> passen wir die Ereignisprozedur, die durch das Ereignis <b>Beim &ouml;ffnen <\/b>ausgel&ouml;st wird, wie in Listing 9 an. Diese pr&uuml;ft nun, ob das &ouml;ffnungsargument aus <b>Me.OpenArgs <\/b>den Wert <b>Freischalten <\/b>enth&auml;lt. Hier ist wichtig, dass Sie <b>Me.OpenArgs <\/b>noch in die <b>Nz<\/b>-Funktion einfassen und den gelieferten Wert im Falle von <b>Null <\/b>in eine leere Zeichenkette umwandeln, da sonst ein Fehler ausgel&ouml;st wird. Enth&auml;lt <b>Me.OpenArgs <\/b>nicht den Wert <b>Freischalten<\/b>, wird der erste Teil der <b>If&#8230;Then<\/b>-Bedingung ausgef&uuml;hrt und Prozedur ruft die Funktion <b>SchluesselPruefen <\/b>auf, die wir ebenfalls ge&auml;ndert haben &#8211; mehr dazu im Anschluss.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Open(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Nz(Me.OpenArgs, \"\") = \"Freischalten\"<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>SchluesselPruefen = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             DoCmd.OpenForm \"frmAnwendung\", OpenArgs:=intFunktionen\r\n             Cancel = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me!txtEMail = DLookup(\"EMail\", \"tblOptionen\")\r\n         Me!txtSchluessel = DLookup(\"Schluessel\", \"tblOptionen\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: Aktionen beim &ouml;ffnen des Formulars frmStart<\/span><\/b><\/p>\n<p>Liefert <b>SchluesselPruefen <\/b>den Wert <b>True<\/b>, &ouml;ffnet die Funktion das Formular <b>frmAnwendung<\/b> und bricht das &ouml;ffnen des Formulars <b>frmStart <\/b>direkt ab. Anderenfalls f&uuml;llt die Prozedur einfach die beiden Felder <b>txtEMail <\/b>und <b>txtSchluessel <\/b>mit den entsprechenden Feldern der Tabelle <b>tblOptionen<\/b>.<\/p>\n<h2>Die neue Funktion SchluesselPruefen<\/h2>\n<p>Die neue Version der Funktion <b>SchluesselPruefen <\/b>finden Sie in Listing 10. Sie liefert einen <b>Boolean<\/b>-Wert als Funktionswert zur&uuml;ck. Sie aktiviert zun&auml;chst das Sanduhr-Symbol, weil die Pr&uuml;fung des Schl&uuml;ssels wie oben erw&auml;hnt mit Ablaufdatum etwas l&auml;nger dauern kann. Dann &ouml;ffnet sie ein Recordset auf Basis der Tabelle <b>tblOptionen <\/b>und schreibt die Werte der beiden Felder <b>EMail <\/b>und <b>Schluessel <\/b>in die Variablen <b>strEMail <\/b>und <b>strSchluessel<\/b>. Dann ruft sie eine weitere Funktion namens <b>SchluesselGueltig <\/b>auf, welche die eigentliche Pr&uuml;fung &uuml;bernimmt und die wir bereits weiter oben vorgestellt haben. Diese Funktion pr&uuml;ft die Kombination aus E-Mail und Schl&uuml;ssel und f&uuml;llt die beiden R&uuml;ckgabeparameter <b>datGueltigBis <\/b>und <b>intFunktionenTemp <\/b>mit dem Ablaufdatum und der Integer-Zahl, welche die freigeschalteten Funktionen repr&auml;sentiert. Sollte die Funktion dann auch noch den Wert <b>True <\/b>zur&uuml;ckgeben, steht einer weiteren Verarbeitung der Daten nichts im Wege. Der Wert des R&uuml;ckgabeparameters <b>intFunktionenTemp <\/b>landet in der &ouml;ffentlich deklarierten Variablen <b>intFunktionen<\/b>. Der Aufruf der Prozedur <b>SchluesselSchreiben <\/b>mit der E-Mail und dem Schl&uuml;ssel als Parameter tr&auml;gt die Daten in die Tabelle <b>tblOptionen <\/b>ein. Der Funktionswert wird auf <b>True<\/b> eingestellt, das aktuelle Formular geschlossen und das Formular <b>frmAnwendung <\/b>ge&ouml;ffnet. Sollte die Kombination aus E-Mail und Schl&uuml;ssel nicht passen, wird eine entsprechende Meldung angezeigt und das Formular <b>frmStart <\/b>bleibt mit leeren Textfeldern ge&ouml;ffnet, sodass der Benutzer die Daten erneut eingeben kann.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>SchluesselPruefen()<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>datGueltigBis<span style=\"color:blue;\"> As Date<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intFunktionenTemp<span style=\"color:blue;\"> As Integer<\/span>\r\n     DoCmd.Hourglass <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblOptionen\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         strEMail = rst!EMail\r\n         strSchluessel = rst!Schluessel\r\n         If SchluesselGueltig(strSchluessel, strEMail, datGueltigBis, _\r\n                 intFunktionenTemp) = <span style=\"color:blue;\">True<\/span> Then\r\n             intFunktionen = intFunktionenTemp\r\n             SchluesselSchreiben strEMail, strSchluessel\r\n             SchluesselPruefen = <span style=\"color:blue;\">True<\/span>\r\n             DoCmd.Close acForm, Me.Name\r\n             DoCmd.OpenForm \"frmAnwendung\"\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"E-Mail-Adresse und\/oder Schl&uuml;ssel sind nicht korrekt.\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     DoCmd.Hourglass <span style=\"color:blue;\">False<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: Pr&uuml;fen, ob der Schl&uuml;ssel noch g&uuml;ltig ist, neue Variante<\/span><\/b><\/p>\n<p>Die Prozedur, die durch die Schaltfl&auml;che <b>cmdOK <\/b>des Formulars <b>frmStart <\/b>ausgel&ouml;st wird, hat sich ebenfalls ge&auml;ndert (siehe Listing 11). Diese liest die E-Mail und den Schl&uuml;ssel aus den Textfeldern ein und ruft die Funktion <b>SchluesselGueltig <\/b>mit den bereits bekannten Parametern auf. Liefert diese Funktion den Wert <b>True <\/b>zur&uuml;ck, k&ouml;nnen wir die zur&uuml;ckgelieferten Parameter auswerten. Der Wert des Parameters <b>intFunktionenTemp <\/b>landet wieder in der global definierten Variablen <b>intFunktionen<\/b>. Die Prozedur <b>SchluesselSchreiben <\/b>tr&auml;gt wieder die E-Mail und den Schl&uuml;ssel in die Tabelle <b>tblOptionen <\/b>ein. Au&szlig;erdem erscheint eine Meldung, welche die erfolgreiche Freischaltung sowie das G&uuml;ltigkeitsdatum mitteilt. Au&szlig;erdem schlie&szlig;t die Prozedur das aktuelle Formular, aktualisiert die Anzeige der Steuer-elemente im Ribbon und &ouml;ffnet das Formular <b>frmAnwendung<\/b>. Falls die Kombination aus E-Mail und Schl&uuml;ssel nicht g&uuml;ltig ist, erscheint eine entsprechende Meldung.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdOK_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>datGueltigBis<span style=\"color:blue;\"> As Date<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSchluessel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intFunktionenTemp<span style=\"color:blue;\"> As Integer<\/span>\r\n     strEMail = Me!txtEMail\r\n     strSchluessel = Me!txtSchluessel\r\n     If SchluesselGueltig(strSchluessel, strEMail, datGueltigBis, _\r\n             intFunktionenTemp) = <span style=\"color:blue;\">True<\/span> Then\r\n         intFunktionen = intFunktionenTemp\r\n         SchluesselSchreiben strEMail, strSchluessel\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Anwendung wurde erfolgreich freigeschaltet.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n             & \"G&uuml;ltig bis: \" & datGueltigBis\r\n         DoCmd.Close acForm, Me.Name\r\n         objRibbon_Main.Invalidate\r\n         DoCmd.OpenForm \"frmAnwendung\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"E-Mail-Adresse und\/oder Schl&uuml;ssel sind nicht korrekt.\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 11: Prozedur f&uuml;r die Schaltfl&auml;che cmdOK des Formulars frmStart<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Sie haben in verschiedenen Stufen Techniken kennengelernt, mit denen Sie die Funktionen einer Anwendung &uuml;ber die Pr&uuml;fung und Speicherung einer Kombination von E-Mail-Adresse und Freischaltungs-Schl&uuml;ssel freischalten k&ouml;nnen. Die dritte Beispieldatenbank <b>Freischaltungsschluessel_III.accdb <\/b>zeigt eine funktionierende L&ouml;sung mit zeitlicher Begrenzung der Funktionen der Anwendung. Dadurch, dass das Ablaufdatum im Freischaltungsschl&uuml;ssel versteckt ist, dauert der Start zwar immer etwa eine Sekunde, aber der Benutzer kann das Ablaufdatum nicht manipulieren.<\/p>\n<p>Sie m&uuml;ssten eine mit diesen Funktionen ausgestattete Datenbank noch in eine <b>.accde <\/b>umwandeln sowie sicher-stellen, dass alle Funktionen der Anwendung vor dem Aufruf auf Basis des Wertes der Variablen <b>intFunktionen <\/b>freigeschaltet oder gesperrt werden.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Freischaltungsschluessel_I.accdb<\/p>\n<p>Freischaltungsschluessel_II.accdb<\/p>\n<p>Freischaltungsschluessel_III.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/AF003C36-6400-44D2-B6C6-A0DB854DEF03\/aiu_1126.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn Sie eine Software weitergeben, wollen Sie nat&uuml;rlich sicherstellen, dass diese nur von Kunden genutzt wird, die auch f&uuml;r die Software bezahlt haben. Wie k&ouml;nnen Sie das sicherstellen Eine M&ouml;glichkeit ist es, in Abh&auml;ngigkeit von einem Benutzernamen einen Freischaltungsschl&uuml;ssel zu erzeugen, den der Benutzer in die Anwendung eingeben muss, damit diese funktioniert. Auf diese Weise sorgen Sie nicht nur daf&uuml;r, dass der Benutzer diesen Schl&uuml;ssel erwerben muss, wenn er die Anwendung nutzen will. Damit ist gleichzeitig sichergestellt, dass Sie &#8211; wenn ein Benutzer die Anwendung weitergibt oder diese sogar in einem Portal zum Download bereitstellt &#8211; herausfinden, welcher Kunde die Software weitergegeben hat. Dieser Beitrag liefert die technischen Grundlagen f&uuml;r den Schutz einer Software mit Freischaltungsschl&uuml;ssel.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66022018,662018,44000027],"tags":[],"class_list":["post-55001126","post","type-post","status-publish","format-standard","hentry","category-66022018","category-662018","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Software freischalten per Schl&uuml;ssel - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Software freischalten per Schl&uuml;ssel\" \/>\n<meta property=\"og:description\" content=\"Wenn Sie eine Software weitergeben, wollen Sie nat&uuml;rlich sicherstellen, dass diese nur von Kunden genutzt wird, die auch f&uuml;r die Software bezahlt haben. Wie k&ouml;nnen Sie das sicherstellen Eine M&ouml;glichkeit ist es, in Abh&auml;ngigkeit von einem Benutzernamen einen Freischaltungsschl&uuml;ssel zu erzeugen, den der Benutzer in die Anwendung eingeben muss, damit diese funktioniert. Auf diese Weise sorgen Sie nicht nur daf&uuml;r, dass der Benutzer diesen Schl&uuml;ssel erwerben muss, wenn er die Anwendung nutzen will. Damit ist gleichzeitig sichergestellt, dass Sie - wenn ein Benutzer die Anwendung weitergibt oder diese sogar in einem Portal zum Download bereitstellt - herausfinden, welcher Kunde die Software weitergegeben hat. Dieser Beitrag liefert die technischen Grundlagen f&uuml;r den Schutz einer Software mit Freischaltungsschl&uuml;ssel.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-13T21:19:07+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"28\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Software freischalten per Schl&uuml;ssel\",\"datePublished\":\"2020-05-13T21:19:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/\"},\"wordCount\":4654,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/b7620d26a74a414bb4a47053f10fff98\",\"articleSection\":[\"2\\\/2018\",\"2018\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/\",\"name\":\"Software freischalten per Schl&uuml;ssel - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/b7620d26a74a414bb4a47053f10fff98\",\"datePublished\":\"2020-05-13T21:19:07+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/b7620d26a74a414bb4a47053f10fff98\",\"contentUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/b7620d26a74a414bb4a47053f10fff98\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Software_freischalten_per_Schluessel\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Software freischalten per Schl&uuml;ssel\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Software freischalten per Schl&uuml;ssel - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/","og_locale":"de_DE","og_type":"article","og_title":"Software freischalten per Schl&uuml;ssel","og_description":"Wenn Sie eine Software weitergeben, wollen Sie nat&uuml;rlich sicherstellen, dass diese nur von Kunden genutzt wird, die auch f&uuml;r die Software bezahlt haben. Wie k&ouml;nnen Sie das sicherstellen Eine M&ouml;glichkeit ist es, in Abh&auml;ngigkeit von einem Benutzernamen einen Freischaltungsschl&uuml;ssel zu erzeugen, den der Benutzer in die Anwendung eingeben muss, damit diese funktioniert. Auf diese Weise sorgen Sie nicht nur daf&uuml;r, dass der Benutzer diesen Schl&uuml;ssel erwerben muss, wenn er die Anwendung nutzen will. Damit ist gleichzeitig sichergestellt, dass Sie - wenn ein Benutzer die Anwendung weitergibt oder diese sogar in einem Portal zum Download bereitstellt - herausfinden, welcher Kunde die Software weitergegeben hat. Dieser Beitrag liefert die technischen Grundlagen f&uuml;r den Schutz einer Software mit Freischaltungsschl&uuml;ssel.","og_url":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-13T21:19:07+00:00","og_image":[{"url":"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"28\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Software freischalten per Schl&uuml;ssel","datePublished":"2020-05-13T21:19:07+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/"},"wordCount":4654,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98","articleSection":["2\/2018","2018","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/","url":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/","name":"Software freischalten per Schl&uuml;ssel - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98","datePublished":"2020-05-13T21:19:07+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#primaryimage","url":"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98","contentUrl":"http:\/\/vg06.met.vgwort.de\/na\/b7620d26a74a414bb4a47053f10fff98"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Software_freischalten_per_Schluessel\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Software freischalten per Schl&uuml;ssel"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001126","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001126"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001126\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}