Avatar billede jgthb Nybegynder
03. august 2006 - 21:13 Der er 26 kommentarer og
1 løsning

application.terminate virker ikke

Hej

jeg har følgende kode:

Problemet er, at 'application.terminate' ikke udføres. Jeg prøvede at se, hvad der skete, hvis jeg byttede om på de to linjer, jeg har fremhævet. Da udførtes ingen af linjerne. Kan nogen hjælpe?

try
  Reg.RootKey:=HKey_Local_Machine;
    if not Reg.OpenKey('\software\microsoft\TInet\serv1\',false) then
    begin
      registrer:=inputbox('Indtast registreringsnøgle','Låsekode: '+kode,'');
      If not validerTekst(registrer) then
      begin
      Showmessage('Forkert registreringskode. Programmet lukkes'); //HERFRA
      application.Terminate; //HERTIL
      end;
...
Avatar billede jgthb Nybegynder
03. august 2006 - 21:25 #1
det virker, hvis jeg skriver halt i stedet for application.terminate. Men jeg er stadig interesseret i svaret. jeg vil dog kun give 30 point nu for et svar.
Avatar billede a_nor Nybegynder
04. august 2006 - 01:19 #2
Hej,

Evt. er der gået noget galt højere oppe i programmet således at stack eller data er kvast. Termintae forsøger at rydde op mens halt bare afbryder = kalder operativsystemet.
Avatar billede martinlind Nybegynder
04. august 2006 - 08:45 #3
I hvilket procedure/event kalder du Terninate !!, man kan nemli' ikke få lov at kalde Terminate i en FormShow() event !!, det kunne også være en grund
Avatar billede a_nor Nybegynder
04. august 2006 - 10:04 #4
Hej Martin Lind

har testet i Delphi 3 med :

procedure TForm1.FormShow(Sender: TObject);
  var i,j:integer;
begin
i:=1;
J:=2;
i:=i-j;
label1.Caption := 'test';
if i<0 then
  begin
  label1.Caption := 'afbryder';
  application.Terminate;
  end
end;

Det stopper programmet fint ?
Avatar billede martinlind Nybegynder
04. august 2006 - 10:13 #5
den plejer at brokke sig hvis du laver en Close i din formshow :)
Avatar billede hrc Mester
04. august 2006 - 17:01 #6
Prøv PostQuitMessage(1) - den virker også fra OnCreate
Avatar billede martinlind Nybegynder
04. august 2006 - 18:27 #7
ja eller en alm. postmessage(); med WM_CLOSE
Avatar billede jgthb Nybegynder
05. august 2006 - 00:15 #8
det er i formCreate.

hvorledes kunne et eksempel se ud for post(quit)message, som I taler om?
Avatar billede a_nor Nybegynder
05. august 2006 - 12:50 #9
Application.terminate virker både i formcreate og som vist ovenfor i formshow.
Hvis man bruger den i formcreate køres også formshow rutinen igennem, hvis den altså er kaldes i den efterfølgende kode (den kode der afvikles indenfor samme event) eller formen autocreates.

Prøv at flytte application.terminate højere op i din kode og se hvad der sker.
Avatar billede hrc Mester
05. august 2006 - 21:43 #10
Her er lige skelettet til en meget primitiv form for adgangskontrol:

const
  RegKey = '\Software\MyFirm\MyProg\';
  RegValue = 'AccessRights';

type
  EAccessRightsException = class(Exception);

procedure TForm1.OnCreate(Sender : TObject);
var
  AccessRights : boolean;
begin
  AccessRights := false;

  try
    with TRegistry.Create do // Åbn registreringsdatabsen
      try
        if OpenKeyReadonly(RegKey) then // Åbn nøglen
          if ValueExists(RegValue) then // Er værdien true så gå videre
            AccessRights := ReadBoolean(RegValue); 

        if not AccessRights then
          raise EAccessRightsException.Create('Insuffient rights for this program');
      finally
        Free;
      end;
  except
    on e: EAccessRightsException do
      PostQuitMessage(1); // Det burde slå programmet ned igen.
  end;
end;
Avatar billede jgthb Nybegynder
05. august 2006 - 22:15 #11
#hrc: Det er meget pænt af dig at komme med et alternativ, men det er egentlig ikke det, jeg ønsker.

#a nor: hvis jeg flytter kode højere på, får jeg følgende fejlmeddelelse:
"Project Project2.exe raised exception class EConvertError with message '''is not a valid integer value. Process stopped. Use Step or Run to continue."

procedure TForm1.FormCreate(Sender: TObject);
var
vaelgordbog: TMenuItem;
i: integer;
Reg: TRegIniFile;
kode,registrer: string;
resultat: integer;
begin
Reg:=TRegIniFile.Create('noegle');
randomize;
kode:=inttostr(random(900000)+99999);
application.Terminate;
try
  Reg.RootKey:=HKey_Local_Machine;
    if not Reg.OpenKey('\software\microsoft\TInet\serv1\',false) then
    begin
      registrer:=inputbox('Indtast registreringsnøgle','Låsekode: '+kode,'');
      If not validerTekst(registrer) then
      begin
      Showmessage('Forkert registreringskode. Programmet lukkes');
      //halt;
      end;
      resultat:=strtoint(kode)*7-strtoint(kode[6]);
      if registrer='' then application.terminate;
      if resultat=strtoint(registrer) then
      begin
        Reg.CreateKey('\software\microsoft\TInet\serv1\');
        reg.CreateKey('\software\microsoft\TInet\serv2\');
        Reg.WriteString('\software\microsoft\TInet\serv1\','Value1','serv1.off');
        reg.WriteString('\software\microsoft\TInet\serv2\','Value1','serv2.off');
      end
      else
        begin
        showmessage('Forkert registeringsnøgle. Programmet lukkes.');
        application.terminate;
        end;
      end;
    finally
    reg.Free;
  end;
...
Avatar billede jgthb Nybegynder
05. august 2006 - 22:24 #12
hov. jeg har da vist noget overskydende kode.
Avatar billede a_nor Nybegynder
06. august 2006 - 07:01 #13
Jamen det var da også OK, så kan man jo prøve om det virker :-)

Når du debugger, i hvilken linie kommer fejlen?

Nu har jeg jo ikke din  "validerTekst(registrer)" funktion,
men uden denne linie kører programmet fint ie. terminerer som det skal.
( Jeg har selvfølgelig lagt application.terminate ned "på plads" (ved halt)

Du burde nok lave en 'exit' efter terminate for ikke at få kørt efterfølgende kode.
Avatar billede hrc Mester
06. august 2006 - 12:02 #14
jgthb: Det var ikke et alternativ jeg kom med. Det var et eksempel på hvordan man brugte PostQuitMessage
Avatar billede jgthb Nybegynder
06. august 2006 - 15:32 #15
a nor: fejlen kommer i linjen "if resultat=strtoint(registrer) then", altså fire linjer under halt. Men det virker, hvis jeg skriver exit efterfølgende, som du foreslog.

hrc: Det må du undskylde. Jeg læste bare den øverste linje, hvor du sagde, det var en primitiv form for adgangskontrol, og da mit også handler om adgang, troede jeg det var et alternativ. Jeg har nu prøvet Postquitmessage både i dit eksempel (redigeret en smule) og i mit program. Det virker fint i dit eksempel, men i mit program virker det ikke, ligesom application.terminate heller ikke virker. Men det lader til at problemet har været den manglende 'exit'-sætning, fordi både postquitmessage og application.terminate virker glimrende med den nu.

alle: bør jeg så bruge enten application.terminate eller postquitmessage nu, eller kan jeg godt bruge halt stadigvæk med god samvittighed? der må jo være en grund til, at man ikke bruger halt hele tiden.
Avatar billede jgthb Nybegynder
06. august 2006 - 15:41 #16
og hvad med close? hvorfor virker det ikke?
Avatar billede a_nor Nybegynder
06. august 2006 - 18:17 #17
Når det virker med din Exit-tilføjelsen, er det fordi der går noget galt i den efterfølgende kode (her StrToInt('') hvis du altså ingen låsekode indtaster).

'Halt' standser uden oprydning (memoryfrigrelse o.a.) mens 'app.terminate' destruerer alle Delphi-objekter. Tilsvarende hvis du selv har lavet noget afslutningskode, så blir dette ikke kaldt hvis du bruger Halt. Jeg kunne forestille mig at app.terminate bl.a. fyrer en PostQuitmessage af ?? men ved det ikke.

Der er Close der ikke kan anvendes i FormCreate.

Ku' godt tænke mig at se din ValiderTekst-kode, jf. dit oprindelige spørgsmål !
Avatar billede martinlind Nybegynder
06. august 2006 - 18:23 #18
Sæt dog et breakpoint i din rutine og step gennem din kode, så ser du hvad der sker :)! hvor sværdt kan det være, alt tyder og lyder som om at du for en exception inden din halt/terminate/eller hvad du nu har gang i, en exception betyder at din kode stoper med at execute og kører en exception rutine i stedet, altså vil du ALDRIG nå ned til din terminate osv., men alt det finder du udaf når du stepper ned igennem med et breakpoint :)
Avatar billede jgthb Nybegynder
06. august 2006 - 20:35 #19
a nor: du skrev: "...fordi der går noget galt i den efterfølgende kode (her StrToInt('') hvis du altså ingen låsekode indtaster)." Problemet opstår også, hvis jeg indtaster bogstaver.
  Tak for forklaringen af halt og close.

martinlind: den når terminate.

Nå. men jeg må hellere give point nu. Eftersom jeg bare ville have det til at virke med application.terminate, og a nor gav mig løsningen 'exit', synes jeg det er rimeligt, at han får flest point. Dog vil jeg også give hrc nogle få point, da han tog sig tid til at forklare mig om postquitmessage. For øvrigt kan du lige se koden, a nor. Her er Validertekst og den fulde FormCreate:

function ValiderTekst(Tekst:String): Boolean;
var
code,v: integer;
Begin
val(tekst,v, Code);
If (code = 0) or (length(tekst)=6) then
Result:=True;
If (code = 0) or (length(tekst)=7) then
Result:=True
else
Result:=false;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
vaelgordbog: TMenuItem;
i: integer;
Reg: TRegIniFile;
kode,registrer: string;
resultat: integer;
begin
Reg:=TRegIniFile.Create('noegle');
randomize;
kode:=inttostr(random(900000)+99999);
try
  Reg.RootKey:=HKey_Local_Machine;
    if not Reg.OpenKey('\software\microsoft\TInet\serv1\',false) then
    begin
      registrer:=inputbox('Indtast registreringsnøgle','Låsekode: '+kode,'');
      If not validerTekst(registrer) then
      if registrer='' then halt else
      begin
      Showmessage('Forkert registreringskode. Programmet lukkes');
      application.terminate;
      exit;
      end;
      resultat:=strtoint(kode)*7-strtoint(kode[6]);
      if resultat=strtoint(registrer) then
      begin
        Reg.CreateKey('\software\microsoft\TInet\serv1\');
        reg.CreateKey('\software\microsoft\TInet\serv2\');
        Reg.WriteString('\software\microsoft\TInet\serv1\','Value1','serv1.off');
        reg.WriteString('\software\microsoft\TInet\serv2\','Value1','serv2.off');
      end;
      end;
    finally
    reg.Free;
  end;
sti:=ExtractFilePath(application.ExeName)+'\';
memoHent.Clear;
memoHent.Lines.LoadFromFile(sti+'data\indstillinger.txt');
billede:=strtoint(memoHent.Lines[0]);
farven:=strtoint(memoHent.lines[1]);
listbox.Font.Size:=strtoint(memoHent.lines[2]);
memoBetydning.Font.Size:=strtoint(memoHent.lines[3]);
BorderStyle := bstoolwindow;
memoHent.Clear;
memoHent.lines.LoadFromFile(sti+'data\navne.txt');
antal:=memoHent.Lines.Count;
labelBundlinje.Caption:=memoHent.lines[0];
listbox.Items.LoadFromFile(sti+'data\opslagsbog.txt');
for i:=1 to memoHent.lines.count do
begin
vaelgordbog:=TMenuItem.Create(MainMenu);
vaelgmenu.add(vaelgordbog);
vaelgordbog.Name:='menuordbog'+inttostr(i);
vaelgordbog.Caption:=memoHent.Lines[i-1];
vaelgordbog.Tag:=i;
vaelgordbog.OnClick:=ordbognummervalg;
end;
ordbogvalg(self);
end;
Avatar billede a_nor Nybegynder
07. august 2006 - 01:02 #20
Din ValiderTekst kommer ud med True hvis teksten er et tal ELLER Der er tastet 7 tilfældige tal, det er vel ikke lige meningen?
Endvidere skal du huske at Terminate ikke afbryder her og nu men at den igangværende kode (FormCreate) eksekveres færdig. Bruger du Exit til at 'komme uden om' anden kode, bliver 'Finally' koden i Try Finally IKKE kørt.

Ved test har jeg fjernet al kode fra sti:=extract....  og frem til sidste end.
Terminate virkede i alle tilfælde, men selvfølgelig får du konverteringsfejl hvis ex. 'abcd' tastes. Så vidt jeg kunne se i Delphi Hjælpen (Delphi 7), kan InputBox anvendes så du er sikker på det er heltal der afleveres.
Avatar billede jgthb Nybegynder
07. august 2006 - 02:23 #21
Er det vigtigt, at finally koden køres. Eller rettere sagt, er det nødvendigt, at reg.free køres? Men hvis det er, så kan jeg vel bare lægge linjen i Formclose eller hvad?

Jeg har omskrevet koden lidt, så nu skulle det gerne virke lidt bedre:

function ValiderTekst(Tekst:String): Boolean;
var
code,v: integer;
Begin
val(tekst,v, Code);
If (code = 0) and (length(tekst)=6) then
Result:=True else
If (code = 0) and (length(tekst)=7) then
Result:=True else
Result:=false;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
vaelgordbog: TMenuItem;
i: integer;
Reg: TRegIniFile;
kode,registrer: string;
resultat: integer;
begin
Reg:=TRegIniFile.Create('noegle');
randomize;
kode:=inttostr(random(900000)+99999);
try
  Reg.RootKey:=HKey_Local_Machine;
    if not Reg.OpenKey('\software\microsoft\TInet\serv1\',false) then
    begin
      registrer:=inputbox('Indtast registreringsnøgle','Låsekode: '+kode,'');
      If not validerTekst(registrer) then
      begin
      Showmessage('Forkert registreringskode. Programmet lukkes');
      application.terminate;
      exit;
      end;
      resultat:=strtoint(kode)*7-strtoint(kode[6]);
      if resultat=strtoint(registrer) then
      begin
        Reg.CreateKey('\software\microsoft\TInet\serv1\');
        reg.CreateKey('\software\microsoft\TInet\serv2\');
        Reg.WriteString('\software\microsoft\TInet\serv1\','Value1','serv1.off');
        reg.WriteString('\software\microsoft\TInet\serv2\','Value1','serv2.off');
      end
      else
      begin
      Showmessage('Forkert registreringskode. Programmet lukkes');
      application.terminate;
      exit;
      end;
      end;
    finally
    reg.Free;
  end;
Avatar billede a_nor Nybegynder
07. august 2006 - 09:57 #22
Nedenstående er generelle betragtninger:

Man bør rydde op, og helst i samme rutine som 'forekomsten' er skabt.
(Du kan ikke 'bare' flytte reg.free til formclose, så skal Reg erklæring også flyttes til Tform1 typen.)

Lav HELE valideringen i ValiderTekst(registerer,kode), læg resultatet i en boolean (eller byte hvis du senere vil lave en samlet fejlmeldingsrutine), og test denne udenfor Try, Finally. (så slipper du også for 2xshowmessage)

PS! husk også lige indrykninger = Hold koden overskuelig.
Avatar billede hrc Mester
07. august 2006 - 10:54 #23
Kunne ikke undgå at bearbejde din kode lidt.

Undgå at indtaste samme tekst flere gange og brug exceptions når de er praktiske. Jeg har lavet en "exception" for "invalid" kode.

Undgå klasser der er ment som en hjælp til overgangen fra win31's ini-filer til win95+ ' registreringsdatabase (TRegIniFile).

Som a_nor skriver: Lav dog koden pænt indrykket (det er en hæslig kodeorden du holder dig).

Skriv variablenavnene ens: Med store og små bogstaver. Undgå "gridlistview" men skriv "GridListView" - og gør det konsekvent. Det bliver mere læseligt på den måde og skulle du forvilde dig over i noget C#, Java eller C / C++ kode (vi kan alle fare vild) så laver du meget færre fejl.

type
  EInvalidRegKey = class(Exception);
 
const
  RegKey = '\Software\Microsoft\TInet\';

function ValiderTekst(const aTekst : string; const aResultat : integer): Boolean;
var
  Code, lgd: integer;
Begin
  result := false;
  Code := IntToStrDef(aTekst,-1);
  if Code <> -1 then
  begin
    lgd := length(aTekst);
    result := lgd in [6,7];
    if result then
      result := resultat = Code;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
  Reg: TRegistry;
  resultat: integer;
  vaelgordbog: TMenuItem;
  kode,registrer: string;
begin
  Randomize;
  kode:=IntToStr(Random(900000)+99999);

  Reg := TRegistry.Create;
  try
    try
      Reg.RootKey:=HKey_Local_Machine;
      if not Reg.OpenKeyReadOnly(RegKey) then // Tjek om det er første gang
      begin
        registrer := InputBox('Indtast registreringsnøgle','Låsekode: '+kode,'');
        resultat := StrToInt(kode) * 7 - StrToInt(kode[6]);
        if not ValiderTekst(registrer,resultat) then
          raise EInvalidRegKey.Create('Forkert registreringskode. Programmet lukkes');
 
        // Er det noget du selv opretter - i Microsofts område?
        // Du burde gemme tingene i den egen gren i databasen
       
        // Hvad med at bruge integers i stedet (fylder mindre og er sikkert hurtigere)?
        // TInet\Serv1 0 - off
        // TInet\Serv2 1 - on
       
        if Reg.OpenKey(RegKey + 'Serv1',true) then
          Reg.WriteString('Value1','serv1.off');
         
        if Reg.OpenKey(RegKey + 'Serv2',true) then
          Reg.WriteString('Value1','serv2.off');
      end;
    except
      on e: EInvalidRegKey do
      begin
        Showmessage(e.Message);
        Application.Terminate; // PostQuitMessage(1);
      end;
      on e: Exception do
      begin
        Showmessage(Fejl opstået under initialisering. Programmet lukkes'#13#10+e.Message);
        Application.Terminate; // PostQuitMessage(1);
      end;
    end; 
  finally
    Reg.Free;
  end;
end;
Avatar billede jgthb Nybegynder
07. august 2006 - 17:04 #24
Nu har jeg lavet koden om. De vigtigste ændringer er følgende:
1) 'Reg.Free' har jeg lagt efter det hele.
2) 'Try' har jeg droppet. Jeg kan faktisk ikke se, hvorfor jeg har brugt den. Det virker fint uden.
3) 'ValiderTekst' har jeg ændret til hrc's forslag. Dog virker 'IntToStrDef' ikke. Jeg går ud fra, du mente 'StrToInt'. Det virker i hvert fald.

Jeg har dog nogle spørgsmål. Et overordnet spørgsmål er, er det bedre nu? Der ud over, forstår jeg ikke linjerne:

"result := lgd in [6,7];
  if result then
    result := resultat = Code; "

Det er jo en boolean, hvordan kan den så sættes lig med noget. Specielt delen "lgd in [6,7]" forstår jeg ikke. En henvisning eller en forklaring ville være rar.

Jeg håber, min kode er mere overskuelig nu. Hvis I synes, pointantallet er urimeligt i forhold til jeres indsats, skal I bare sige til. Og her får I koden:
"
function ValiderTekst(Tekst:String;ResultatVal:Integer): Boolean;
var
Code,Laengde: Integer;
Begin
Result:=False;
Code:=StrToIntDef(Tekst,-1);
if Code <> -1 then
begin
  Laengde:=Length(Tekst);
  Result:=Laengde in [6,7];
  if Result then Result:=resultatval = Code;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
Vaelgordbog: TMenuItem;
I: integer;
Reg: TRegIniFile;
Kode,Registrer: string;
Resultat: integer;
Boks: boolean;
begin
Reg:=TRegIniFile.Create('noegle');
Reg.RootKey:=HKey_Local_Machine;
if not Reg.OpenKey('\software\microsoft\TInet\serv1\',false) then
begin
  Randomize;
  Kode:=IntToStr(Random(900000)+99999);
  Resultat:=StrToInt(Kode)*7-StrToInt(Kode[6]);
  Boks:=InputQuery('Indtast registreringsnøgle','Låsekode: '+Kode,Registrer);
  if not Boks then Application.Terminate;
  If not ValiderTekst(Registrer,Resultat) then
  begin
    Showmessage('Forkert registreringskode. Programmet lukkes');
    Application.Terminate;
  end
  else
  begin
    Reg.CreateKey('\software\microsoft\TInet\serv1\');
    Reg.CreateKey('\software\microsoft\TInet\serv2\');
    Reg.WriteString('\software\microsoft\TInet\serv1\','Value1','serv1.off');
    Reg.WriteString('\software\microsoft\TInet\serv2\','Value1','serv2.off');
  end;
end;
Reg.Free;
"
Avatar billede jgthb Nybegynder
07. august 2006 - 17:14 #25
Nå jo, jeg glemte lige det angående registreringsdatabasen. Det er mine egne tilføjelser. Grunden til, jeg har givet dem den placering, er, at jeg ikke vil have, at folk bare lige skal kunne finde dem. De har ingen betydning overhovedet for programmet andet end, at '\software\microsoft\TInet\serv1\' giver adgang, hvis den eksisterer. Er det dumt, at jeg har givet dem den placering?
  For øvrigt, findes der nogle tal, som er specifikke for hver enkelt computer, ligesom mac-adressen. Jeg vil nemlig godt gøre sådan, at der skal være en bestemt kode til hver computer, i stedet for at der genereres en ny kode hver gang. Det skal dog ikke være selve mac-adressen, da jeg ikke kan finde ud af at få den frem. (og ja, jeg har læst om det her). Så måske et andet tal? Men nu bevæger jeg mig selvfølgelig endnu længere væk fra det oprindelige spørgsmål.
Avatar billede hrc Mester
07. august 2006 - 20:38 #26
Mac-adressen kan i øvrigt også ændres og hvad nu hvis der skiftes netkort? Ikke desto mindre tror jeg at Windows XP genererer en eller anden unik nøgle på baggrund af den.

Jeg har selv hentet det hedgangne TorboPowers modul: OnGurad der netop kan det der med serienumre og rettigheder. Prøv eventuelt at kigge i på den: http://sourceforge.net/projects/tponguard/
Avatar billede jgthb Nybegynder
10. august 2006 - 23:44 #27
jeg giver point i morgen, hvis du ville have en del af pointene, hrc
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester