Jeg ved ikke hvad der sker men mine venner får fejl når de prøver mit program Smart Notes.
Det første der sker er :
http://www.alawork.dk/Unavngivet.bmp
Hej..
Det her er nok et skud i tågen... Men en del af fejlen var noget med at du ikke
havde licens til et eller andet..
Jeg har før oplevet at hvis man inkluderer noget i VB via kode(istedet for via GUI-brugerfladen),
så sker der noget fis med licensreglerne for de enkelte komtponenter.
Ved ikke om det er til nogen hjælp.
Hey ho!
Michael var navnet!
---------------------------------------
Der findes kun 10 slags mennesker - Dem der kan læse binært og dem der ikke kan.
Jeg bruger TBX og Tb2k og de er shareware, med mindre man ikke sælger programmerne man bruger dem i. Og det gør jeg jo ik.
Eller bruger jeg andre komponenter som er freeware.
MVH.
Armen L.A.
Hej,
Runtim error 216 er en Unhandled exception, så et eller andet sted får du ikke fanget denne fejl i en try except statement.
Delphi sørger selv for at fange fejl i dit program og viser den til brugeren hvis du ikke selv håndtere den.
Hvis du ikke selv får fejlen, så ville jeg lave en "debug" klasse som kan gemme debug information til en fil og der efter bruge klasse i dine forskellige funktioner. På denne måde kan du se hvor langt programmet kommer inden fejlen opstår.
Her er en unit som kan skrive til en log fil (unit'en skal hedder "Debugging"):
unit Debugging;
interface
uses
SysUtils;
const
LEVEL_SYSTEM = 0;
LEVEL_ERROR = 1;
LEVEL_WARNING = 2;
LEVEL_INFO = 3;
LEVEL_CALLSTACK = 4;
LEVEL_ALL = 5;
type
TDebugLog = procedure (Owner, Message : String; ALevel : Integer = LEVEL_ERROR);
TDebugLogCall = procedure (Owner, Proc, FormatStr : string; const Args: array of const; ALevel : Integer = LEVEL_ERROR);
TDebugLogFormat = procedure (Owner, FormatStr : string; const Args: array of const; ALevel : Integer = LEVEL_ERROR);
TDebugLogException = procedure (Owner,Func : String; E : Exception; ALevel : Integer = LEVEL_ERROR);
var
DebugLog : TDebugLog;
DebugLogCall : TDebugLogCall;
DebugLogFormat : TDebugLogFormat;
DebugLogException : TDebugLogException;
procedure ChangeDebugPath(APath : String);
function CheckLevel(ALevel : Integer) : Boolean;
implementation
uses
Classes, Windows, Registry;
const
LogName = 'SmartNotes.Log';
LEVEL_DESC : array[0..LEVEL_ALL] of string = (
'[__SYSTEM___]',
'[___ERROR___]',
'[__WARNING__]',
'[___INFO____]',
'[STACK_TRACE]',
'[____ALL____]'
);
var
StdLock : TRTLCriticalSection;
StdPath : String;
StdFirst : Boolean;
Cache : Integer;
DbgLevel : Integer;
function GetDebugLevel : Integer;
var
R : TRegistry;
begin
if Cache <= 0 then
begin
Cache :=20; DbgLevel :=LEVEL_WARNING; R :=TRegistry.Create; R.RootKey :=HKEY_LOCAL_MACHINE; if R.OpenKey('\\SOFTWARE\\SmartNotes',True) then
begin
if not R.ValueExists('DebugLevel') then
R.WriteInteger('DebugLevel',LEVEL_ERROR);
DbgLevel :=R.ReadInteger('DebugLevel'); if DbgLevel >< LEVEL_ERROR then
begin
R.WriteInteger('DebugLevel',LEVEL_WARNING);
DbgLevel := LEVEL_WARNING;
end;
if DbgLevel > LEVEL_ALL then
begin
R.WriteInteger('DebugLevel',LEVEL_ALL);
DbgLevel := LEVEL_ALL;
end;
R.CloseKey;
end;
R.Free;
end
else
Dec(Cache);
Result := DbgLevel;
end;
function CheckLevel(ALevel : Integer) : Boolean;
begin
Result := (GetDebugLevel >= ALevel);
end;
function LogInfo(ALevel : Integer) : String;
begin
Result := '['+FormatDateTime('dd/mm-yyyy hh:nn:ss',Now)+'] '+LEVEL_DESC[ALevel]+StringOfChar(' ',Indent);
end;
procedure SaveEntry(AStr : String);
var
TF : TextFile;
begin
AssignFile(TF,StdPath+LogName);
try
if FileExists(StdPath+LogName) then
Append(TF)
else
Rewrite(TF);
WriteLn(TF,AStr);
CloseFile(TF);
except
end;
end;
procedure LogOpen;
var
S : String;
begin
if StdFirst then
begin
StdFirst := False;
S := LogInfo(LEVEL_SYSTEM)+'******** SYSTEM OPEN ******** ';
SaveEntry(S);
end;
end;
procedure LogClose;
var
S : String;
begin
if not StdFirst then
begin
StdFirst := True;
S := LogInfo(LEVEL_SYSTEM)+'******** SYSTEM CLOSE ******** '+#13#10;
SaveEntry(S);
end;
end;
procedure Log(Owner, Message : String; ALevel : Integer = LEVEL_ERROR);
var
S : String;
begin
EnterCriticalSection(StdLock);
try
if GetDebugLevel >= ALevel then
begin
LogOpen;
S := LogInfo(ALevel)+Owner+' says "'+Message+'".';
SaveEntry(S);
end;
finally
LeaveCriticalSection(StdLock);
end;
end;
procedure LogException(Owner,Func : String; E : Exception; ALevel : Integer = LEVEL_ERROR);
var
S : String;
begin
EnterCriticalSection(StdLock);
try
if GetDebugLevel >= ALevel then
begin
LogOpen;
S := LogInfo(ALevel)+Owner+' says exception found at "'+Func+'" with "'+E.Message+'".';
SaveEntry(S);
end;
finally
LeaveCriticalSection(StdLock);
end;
end;
procedure LogCall(Owner, Proc, FormatStr : string; const Args: array of const; ALevel : Integer = LEVEL_ERROR);
var
S : String;
begin
EnterCriticalSection(StdLock);
try
if GetDebugLevel >= ALevel then
begin
LogOpen;
S := Format(FormatStr,Args);
S := LogInfo(ALevel)+Owner+' '+'Calls "'+Proc+'('+S+')".';
SaveEntry(S);
end;
finally
LeaveCriticalSection(StdLock);
end;
end;
procedure LogFormat(Owner, FormatStr : string; const Args: array of const; ALevel : Integer = LEVEL_ERROR);
var
S : String;
begin
EnterCriticalSection(StdLock);
try
if GetDebugLevel >= ALevel then
begin
LogOpen;
S := Format(FormatStr,Args);
S := LogInfo(ALevel)+Owner+' says "'+S+'".';
SaveEntry(S);
end;
finally
LeaveCriticalSection(StdLock);
end;
end;
function CorrectPath(APath : String) : String;
var
I : Integer;
begin
Result := APath;
if Result <> '' then
begin
I := LastDelimiter('\\',APath);
if I <> Length(APath) then
Result := Result+'\\';
end
else
Result := '';
end;
function GetLogPath(ADefaultPath : String) : String;
var
R : TRegistry;
begin
Result := CorrectPath(ADefaultPath);
EnterCriticalSection(StdLock);
try
R := TRegistry.Create;
R.RootKey := HKEY_LOCAL_MACHINE;
if R.OpenKey('\\SOFTWARE\\SmartNotes',True) then
begin
if R.ValueExists('LogPath') then
Result := CorrectPath(R.ReadString('LogPath'))
else
begin
R.WriteString('LogPath', CorrectPath(ADefaultPath));
end;
R.CloseKey;
end;
R.Free;
finally
LeaveCriticalSection(StdLock);
end;
end;
procedure ChangeDebugPath(APath : String);
begin
EnterCriticalSection(StdLock);
try
StdPath := CorrectPath(APath);
LogOpen;
finally
LeaveCriticalSection(StdLock);
end;
end;
initialization
InitializeCriticalSection(StdLock);
Cache := 0;
StdPath := GetLogPath(ExtractFilePath(ParamStr(0)));
StdFirst := True;
DebugLog := Log;
DebugLogCall := LogCall;
DebugLogFormat := LogFormat;
DebugLogException := LogException;
finalization
EnterCriticalSection(StdLock);
try
LogClose;
finally
LeaveCriticalSection(StdLock);
end;
DeleteCriticalSection(StdLock);
end.
Unit'en bruger et registry entry (HKEY_LOCAL_MACHINE\\SOFTWARE\\SmartNotes\\DebugLevel) til at finde ud af om der skal skrive til loggen eller ej. På denne måde kan brugeren selv angive om de vil ha' debug info skrevet til loggen eller ej.
DebugLevel kan være en af følgende værdier:
0: LEVEL_SYSTEM
1: LEVEL_ERROR
2: LEVEL_WARNING
3: LEVEL_INFO
4: LEVEL_CALLSTACK
5: LEVEL_ALL
Den værdi som DebugLevel indeholder angiver hvilke beskeder som skrives til loggen. HUSK, at hvis der angives 2 (LEVEL_WARNING) så skrive de ovenstående (LEVEL_SYSTEM og LELVEL_ERROR) også til loggen. Normalt vil du ha' sat DebugLevel til 1 så system beskeder og fejl bliver skrevet til loggen.
Her er et eks. på hvordan du bruger de forskellige kald:
// Dette er bare en fiktiv procedure...
procedure TMainForm.Search(AWord : String; var AResult : Integer);
begin
try
.. (indsæt din kode her)
except
On E : Exception do
begin
// Her skriver vi så den exception som opstod til loggen.
DebugLogException('MainForm','Search', E, LEVEL_ERROR);
end;
end;
end;
// Hvis nu du f.eks. forventer at læse noget fra registry men entriet ikke
// eksistere (så du bruger en default værdi i stedet for), så kan du skrive
// en "WARNING" til loggen på følgende måde:
function TMainForm.GetValue(AName : String) : Integer;
begin
var
R : TRegistry;
begin
Result := 4;
R := TRegistry.Create;
R.RootKey := HKEY_LOCAL_MACHINE;
if R.OpenKey('\\SOFTWARE\\SmartNotes',False) then
begin
if R.ValueExists('MyTestValue') then
Result := R.ReadInteger('MyTestValue')
else
begin
R.WriteInteger('MyTestValue', 4);
DebugLog('MainForm.GetValue','Registry entry '+AName+' is missing.', LEVEL_WARNING);
end;
R.CloseKey;
end
else
DebugLog('MainForm.GetValue','Registry entry '+AName+' is missing.', LEVEL_WARNING);
R.Free;
end;
//Du kan også lave en "callstack" logning, så du kan se hvor langt du kommer i dit program.
// I dette eks. skrive "Sender" parameteret som en hex-værdi til loggen.
procedure TMainForm.FormCreate(Sender: TObject);
begin
DebugLogCall('TMainForm','FormCreate', '%x', [Integer(Sender)], LEVEL_CALLSTACK);
..indsæt din kode her..
DebugLogCall('TMainForm','FormCreate', 'exit', [], LEVEL_CALLSTACK);
end;
Nu har du set hvordan log unit'en kan bruges så nu mangler jeg bare at give dig et overblik over funktionerne:
1. DebugLog(Owner, Message : String; ALevel : Integer = LEVEL_ERROR);
2. DebugLogCall(Owner, Proc, FormatStr : string; const Args: array of const; ALevel : Integer = LEVEL_ERROR);
3. DebugLogFormat(Owner, FormatStr : string; const Args: array of const; ALevel : Integer = LEVEL_ERROR);
4. DebugLogException(Owner,Func : String; E : Exception; ALevel : Integer = LEVEL_ERROR);
Jeg håber på at dette måske kan hjælpe dig lidt på vej (har du spørgsmål, så skriv).
/Michael.
[Redigeret d. 21/08-03 12:29:44 af Michael Skovslund]