| Autor |
Beitrag |
Masterhawk
      
Beiträge: 92
Win 2000,Win XP
D6 Pers
|
Verfasst: Di 03.01.06 02:05
Ich habe ein Problem in einem meiner Programme:
Es soll der Inhalt einer Datei ausgelesen werden, aber die Datei ist verschlüsselt, ergo wird die Datei vorher entschlüsselt. Dann soll das Programm eine einfache txt Datei auslesen. Der Haken ist, das die Datei nicht fertig entschlüsselt ist, oder zumindest liegt sie noch nicht richtig vor, sodass es zu lesefehlern kommt wenn das Programm sie auslesen will. Ich hab alle möglichen Befehle und Algorithmen ausprobiert, doch ich kann nicht auf die fertigstellung der Datei warten,, zumindest ist sie nie fertig.
Da das Entschlüsseln in einem eigenen Thread von statten geht ist die einzige Möglichkeit den Thread "zu fragen" wann er fertg ist.....Nu die Frage:
Wie kann ich überprüfen(permanent!) ob ein Thread beendet wurde. Dies muss aus einer DLL heraus möglich sein, da der Code aus eben solch einer Datei ausgeführt wird. Hoffe ich konnte mein Problem einigermaßen verständlich erläutern....
Thx for help
|
|
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 03.01.06 03:26
Probier mal TThread.Waitfor
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.01.06 10:05
Benutzt die die Thread-Klasse oder erzeugst du deinen Tread von Hand mit BeginThread? Bei zweiteren wäre bestimmt WAITFORSINGLEOBJECT interessant für dich.
|
|
Masterhawk 
      
Beiträge: 92
Win 2000,Win XP
D6 Pers
|
Verfasst: Di 03.01.06 15:27
@Spaceguide: das mit waitfor hab ich auch schon probiert...auf welchen wert muss ich warten..und wie überprüfe ich permanent ob das erfüllt ist(Non-VCL), oder muss ich das nicht.
@Luckie: bei dem Link findet er nichts, aber der Thread ist aus einer Klasse abgeleitet....
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure RunDecodeThread(Filename, Folder, PW, HashEncodedFile: string; HashClass: ThashClass; CipherClass: TCipherClass; hWnd: THandle); begin DThread := TDecodeThread.Create(True); DThread.Priority := tpNormal; DThread.FreeOnTerminate := True; DThread.FFilename := Filename; Dthread.FFolder := Folder; DThread.FPW := PW; DThread.FHashEncodedFile := HashEncodedFile; DThread.FHashClass := HashClass; DThread.FCipherClass := CipherClass; DThread.FHandle := hWnd; DThread.FBlockSize := BlockSize; DThread.Resume;
end; |
ich will warten bis DThread beendet wurde
Aber wie ich grade sehe ist das dein Tutorial über Encryption und so....da bist du ja der beste ansprechpertner....perfekt
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137:
| unit DecodeThread;
interface
uses Windows, Classes, SysUtils, Cryption, StreamProgressAdapter, Hash, Cipher,Unit1;
type TDecodeThread = class(TThread) private public FFilename: string; FFolder: string; FPW: string; FHashEncodedFile: string; FHashClass: THashClass; FCipherClass: TCipherClass; FHandle: THandle; FBlockSize: Integer; FNewFilename: string; function DecodeFile(Filename, Folder, PW: string; Cipher: TCipherClass; hWnd: THandle): Boolean; protected procedure Execute; override; end;
implementation
{$INCLUDE CrypterHelpers.inc}
function TDecodeThread.DecodeFile(Filename, Folder, PW: string; Cipher: TCipherClass; hWnd: THandle): Boolean; var SrcStream: TStreamProgressAdapter; DestStream: TFileStream; Len: Integer; Buffer: Pointer; begin result := False; SrcStream := TStreamProgressAdapter.Create(TFileStream.Create(Filename, fmOpenRead), hWnd); if Assigned(SrcStream) then begin try if ExtractFileExt(Filename) = EXTENSION then FNewFilename := ExtractFilename(ChangeFileExt(Filename, '')) else FNewFilename := ExtractFilename(ChangeFileExt(Filename, '')) + '.tmp'; DestStream := TFileStream.Create(IncludeTrailingPathDelimiter(Folder) + FNewFilename, fmCreate); if Assigned(DestStream) then begin try SrcStream.Seek(sizeof(TFileHeader), soFromBeginning); DefCipherClass := FCipherClass; GetMem(Buffer, 1024); try with DefCipherClass.Create(PW, nil) do begin Mode := cmCBC; InitKey(PW, nil); while (SrcStream.Position < SrcStream.Size) and (Terminated = False) do begin if SrcStream.Size - SrcStream.Position > BlockSize then Len := BlockSize else Len := SrcStream.Size - SrcStream.Position; SrcStream.ReadBuffer(Buffer^, Len); DecodeBuffer(Buffer^, Buffer^, Len); DestStream.WriteBuffer(Buffer^, Len); end; end; finally FreeMem(Buffer); end; finally FreeAndNil(DestStream); end; end else begin RaiseLastOSError(); exit; end; finally FreeAndNil(SrcStream); end; end else begin RaiseLastOSError(); exit; end; result := True; form1.ContinueRead:=true; end;
procedure TDecodeThread.Execute; var HashDecodedFile: string; begin if not DecodeFile(FFilename, FFolder, FPW, FCipherClass, FHandle) then Messagebox(Handle, 'Fehler beim Entschlüsseln der Datei.', 'Datei entschlüsseln', MB_ICONSTOP); HashDecodedFile := GenerateFileHash(FFolder + FNewFilename, FHashClass, FHandle); if FHashEncodedFile <> HashDecodedFile then Messagebox(FHandle, PChar('Entschlüsselte Datei ist beschädigt.'#13#10 + 'Prüfsumme verschlüsselte Datei: ' + FHashEncodedFile + #13#10 + 'Prüfsumme entschlüsselte Datei: ' + HashDecodedFile + #13#10#13#10 + 'Überprüfen sie das Passwort.'), 'Prüfsumme', MB_ICONSTOP); end;
end. |
wie gesagt ich will warten bis die decode datei vorliegt und dann soll sie ausgelesen werden....
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.01.06 15:29
Ja, MS hat bei seiner Suche was geändert, aber der Haustechniker ist per ICQ schon informiert. 
|
|
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 03.01.06 15:34
Also bei FreeOnTerminate=True ist Waitfor natürlich denkbar schlecht. Du kannst natürlich auch über SendMessage eine Nachricht an dein Fenster schicken, um es so über die Fertigstellung zu benachrichtigen.
|
|
Masterhawk 
      
Beiträge: 92
Win 2000,Win XP
D6 Pers
|
Verfasst: Mi 04.01.06 17:22
Nix funktioniert....
Hoffe ja das Luckie mir was schreibt....  *hoff*
Hier ist die Function:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| function LoadCurrRecord(Mode : ShortString;ID:Cardinal;Handle:HWND) : TRecord; stdcall; var pBuff,pID:string; begin GetDir(0,HomeDir); if FileExists(HomeDir+'\'+Mode+'.txt.h2c') then begin Decode(HomeDir+'\'+Mode+'.txt.h2c',Homedir+'\',PSWD,Handle); if FileExists(HomeDir+'\'+Mode+'.txt') then begin
AssignFile(f_HSC,HomeDir+'\'+Mode+'.txt'); Reset(f_HSC); readln(f_HSC,pBuff); readln(f_HSC,pID); if StrToInt(pID)=ID then begin result.Min:=StrToInt(pBuff[1]); result.Sec:=StrToInt(pBuff[2]+pBuff[3]); result.mSec:=StrToInt(pBuff[4]+pBuff[5]); end else begin MessageDlg(E001,mtError,[mbOk],0); result.Min:=0; result.Sec:=0; result.mSec:=0; end; CloseFile(f_HSC); Encode(HomeDir+'\'+Mode+'.txt',Homedir+'\',PSWD,Handle); end; end else begin result.Min:=0; result.Sec:=0; result.mSec:=0; end; end; |
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 04.01.06 21:07
Was soll ich dir denn schreiben? Wi du auf deinen Thread wartest hat dir doch schon Spaceguide geschrieben.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mi 04.01.06 21:25
Man sollte den Thread vielleicht über Terminate := True beenden, vielleicht fehlt das.
_________________ Na denn, dann. Bis dann, denn.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 05.01.06 06:04
Masterhawk hat folgendes geschrieben: | Aber wie ich grade sehe ist das dein Tutorial über Encryption und so....da bist du ja der beste ansprechpertner....perfekt
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137:
| unit DecodeThread;
interface
uses Windows, Classes, SysUtils, Cryption, StreamProgressAdapter, Hash, Cipher,Unit1;
type TDecodeThread = class(TThread) private public FFilename: string; FFolder: string; FPW: string; FHashEncodedFile: string; FHashClass: THashClass; FCipherClass: TCipherClass; FHandle: THandle; FBlockSize: Integer; FNewFilename: string; function DecodeFile(Filename, Folder, PW: string; Cipher: TCipherClass; hWnd: THandle): Boolean; protected procedure Execute; override; end;
implementation
{$INCLUDE CrypterHelpers.inc}
function TDecodeThread.DecodeFile(Filename, Folder, PW: string; Cipher: TCipherClass; hWnd: THandle): Boolean; var SrcStream: TStreamProgressAdapter; DestStream: TFileStream; Len: Integer; Buffer: Pointer; begin result := False; SrcStream := TStreamProgressAdapter.Create(TFileStream.Create(Filename, fmOpenRead), hWnd); if Assigned(SrcStream) then begin try if ExtractFileExt(Filename) = EXTENSION then FNewFilename := ExtractFilename(ChangeFileExt(Filename, '')) else FNewFilename := ExtractFilename(ChangeFileExt(Filename, '')) + '.tmp'; DestStream := TFileStream.Create(IncludeTrailingPathDelimiter(Folder) + FNewFilename, fmCreate); if Assigned(DestStream) then begin try SrcStream.Seek(sizeof(TFileHeader), soFromBeginning); DefCipherClass := FCipherClass; GetMem(Buffer, 1024); try with DefCipherClass.Create(PW, nil) do begin Mode := cmCBC; InitKey(PW, nil); while (SrcStream.Position < SrcStream.Size) and (Terminated = False) do begin if SrcStream.Size - SrcStream.Position > BlockSize then Len := BlockSize else Len := SrcStream.Size - SrcStream.Position; SrcStream.ReadBuffer(Buffer^, Len); DecodeBuffer(Buffer^, Buffer^, Len); DestStream.WriteBuffer(Buffer^, Len); end; end; finally FreeMem(Buffer); end; finally FreeAndNil(DestStream); end; end else begin RaiseLastOSError(); exit; end; finally FreeAndNil(SrcStream); end; end else begin RaiseLastOSError(); exit; end; result := True; form1.ContinueRead:=true; end;
procedure TDecodeThread.Execute; var HashDecodedFile: string; begin if not DecodeFile(FFilename, FFolder, FPW, FCipherClass, FHandle) then Messagebox(Handle, 'Fehler beim Entschlüsseln der Datei.', 'Datei entschlüsseln', MB_ICONSTOP); HashDecodedFile := GenerateFileHash(FFolder + FNewFilename, FHashClass, FHandle); if FHashEncodedFile <> HashDecodedFile then Messagebox(FHandle, PChar('Entschlüsselte Datei ist beschädigt.'#13#10 + 'Prüfsumme verschlüsselte Datei: ' + FHashEncodedFile + #13#10 + 'Prüfsumme entschlüsselte Datei: ' + HashDecodedFile + #13#10#13#10 + 'Überprüfen sie das Passwort.'), 'Prüfsumme', MB_ICONSTOP); end;
end. |
|
Mir ist nicht bekannt, dass ich ein Tutorial über Verschlüsselungs-algorithmen geschrieben hätte, aber dass sieht ganz nach meinem Code aus, das stimmt.
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Do 05.01.06 09:25
Ich will ja nicht unken. Aber wenn du auf einen Thread wartest bis er fertig macht doch der Thread recht wenig, wenn nicht sogar überhaupt keinen, Sinn mehr! Kann natürlich auch sein, dass mir der tiefere Sinn dahinter verborgen geblieben ist. Sinn und Zwecks von Threads ist es ja nun mal arbeiten zu parallelisieren. Und das bedeitet nun mal der Thread wird angeworfen und arbeitet so lange bis er fertig ist und dann bekommt jemand bescheid gesagt.
Da du mit Klassen arbeitest. Wenn es immer noch unbedingt ein Thread sein muss hast du dir dann schon mal überlegt das Event OnTerminate zu benutzen. Wenn der Thread fertig ist wird dieses Synchronisiert aufgerufen. Deine Anwendung kann solange der Thread läuft die GUI grundsätzlich sperren. Und wenn das Event aufgerufen wird wird die GUI ensperrt. So hast du den Vorteil, dass sie nicht stehen bleibt. Wie es bei WaitFor etc der Fall ist.
Muss aber gestehen, dass die Synchronisierung in DLLs ein wenig trickreich ist. Aber wie gesagt wenn ich das alles so richtig verstanden ist der Thread ein wenig überflüssig.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 05.01.06 14:39
Lossy eX hat folgendes geschrieben: | | Ich will ja nicht unken. Aber wenn du auf einen Thread wartest bis er fertig macht doch der Thread recht wenig, wenn nicht sogar überhaupt keinen, Sinn mehr! |
Doch macht er sehr wohl. Ohne den Thread würde das Fenster nicht aktualisiert werden und "einfrieren". Schlimmsten Falls würde Windows sogar im Taskmanager das Fenster als "Reagiert nicht" markieren.
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Fr 06.01.06 08:51
Das magst du durchaus recht haben. Vorrausgesetzt ich habe das alles richtig verstanden. Das Thema ist ein wenig konfus geschrieben. Vor allem am frühen morgen.  Aber wenn man aus dem Hauptfenster mit WaitFor oder WaitForSingleObject (je nachdem wie man es benutzt) auf das Ende des Threads wartet, dann erreicht man auch genau dieses Effekt als wie wenn man es ohne Thread startet. Nämlich, dass die Anwenung so lange Blockiert bis der Thread zu Ende ist und in solch einem Fall macht ein Thread nur wirklich keinen Sinn mehr.
Wobei ich persönlich für so etwas eigentlich immer das Event OnTerminate benutze und damit bisher ganz gut gefahren bin. Da hat man auch den Vorteil, dass die entsprechende Info gepushed wird und nicht gepolled werden muss.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 06.01.06 13:40
Das muss man entweder mit einen zweiten Thread regeln oder man macht so was:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function WaitForThread(ThreadFunc: TThreadFunc; Params: PThreadParams; MsgMask: Integer = QS_ALLINPUT): DWORD; var hThread : THandle; ThreadID : Cardinal; waitResult : DWord; begin hThread := BeginThread(nil, 0, ThreadFunc, Params, 0, ThreadID);
repeat waitResult := MsgWaitForMultipleObjects(1, hThread, False, INFINITE, MsgMask); if waitResult = WAIT_OBJECT_0 + 1 then ProcessMessages(0); until waitResult = WAIT_OBJECT_0;
result := 0; if Params <> nil then FreeMem(Params); CloseHandle(hThread); end; |
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Fr 06.01.06 14:03
Als Timeout sollte dann aber nicht unbedingt INFINITE gesetzt werden.  Ich denke mal 50 oder 100 sollten vollkommen ausrechen.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 06.01.06 14:07
In meinem Fall wußte ich aber nicht, wie lange der Thread braucht. Einen Timeout konnte ich da nicht setzen.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 06.01.06 14:49
@Luckie: Wieso WaitForMultipleObjects? Wo setzt Du das zweite Object überhaupt?
@Timeout: 100 sollt möglich sein; das wird vom jetzigen Source bereits korrekt behandelt.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 06.01.06 19:11
Und wenn er eine größere Datei verschlüsselt oder die Datei auf einem Netzlaufwerk liegt?
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 06.01.06 21:26
BenBE hat folgendes geschrieben: | | @Luckie: Wieso WaitForMultipleObjects? Wo setzt Du das zweite Object überhaupt? |
Uff, also der Code stammt ursprünglich von Motzi. Dass da WaitForMultipleObjects steht fällt mir erst jetzt auf. Mach ihn doch mal darauf aufmerksam.
|
|
tommie-lie
      
Beiträge: 4373
Ubuntu 7.10 "Gutsy Gibbon"
|
Verfasst: Fr 06.01.06 23:24
BenBE hat folgendes geschrieben: | | @Luckie: Wieso WaitForMultipleObjects? Wo setzt Du das zweite Object überhaupt? |
Ganz einfach  :
[ ] MsgWaitForSingleObject() existiert.
Allerdings:
Ich weiß nicht, wie die Delphi-Deklaration lautet, aber eigentlich soll da eigentlich (sprich: in C) ein Zeiger auf das erste Handle übergeben werden, Msg...jects(1, @hThread, ...) wäre also vielleicht eher dem Zwecke dienlich, wenn Delphi das nicht mit einer überladenen Deklaration mit var-Parameter regelt (wäre nicht nur hässlich, sondern würde auch so aussehen, deswegen hoffe ich für Borland, daß sie's nicht gemacht haben  ).
Ob Infinite oder nicht ist übrigens egal, aber Infinite wäre mir lieber. Die Funktion kehrt zurück, sobald eine Nachricht eintrudelt oder das Objekt, auf das gewartet wird (hier der Thread), signalled wird. Soll sowieso sichergestellt werden, daß es bis zum Ende des Threads wartet, kann ich auch infinite warten. Entweder kehrt der Thread zurück, oder ich habe sowieso eine Situation, die mir nicht gefällt. Mit einem unötigen Timeout nach 100 Milliesekunden verbrate ich allerhöchstens unnötig Rechenleistung für die Schleife. Da sowieso auf WAIT_OBJECTS_0+1 geprüft wird, würde nach dem Timeout nichtmal ProcessMessages() aufgerufen werden, sondern einfach nur erneut Msg...jects().
_________________ Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
|
|
|