AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Pegasus: Luckies persönliches Synchronisationstool
Thema durchsuchen
Ansicht
Themen-Optionen

Pegasus: Luckies persönliches Synchronisationstool

Ein Thema von Luckie · begonnen am 28. Feb 2005 · letzter Beitrag vom 8. Jan 2009
Antwort Antwort
Seite 9 von 11   « Erste     789 1011      
Benutzerbild von Luckie
Luckie
Registriert seit: 29. Mai 2002
Und zwar geht es darum, wenn man ein transportables Speichermedium benutzt, möchte man das eventuell mit einem Verzeichnis auf der Festplatte synchronisieren. Jetzt könnte man es sich einfach machen und einfach das entsprechende Verzeichnis auf dem USB Stick löschen und das von der Festplatte auf den USB Stick kopieren. Nun ist das natürlcih nicht sehr elegant und für den USB Stick nicht sehr schön, da solche Speichermedien nur begrenzt beschrieben werden können. Lese- und Schreibzugriffe sollten also auf ein Mindestmaß reduziert werden.

Hier kommt mein Programm ins Spiel, das mag es zwar schon geben, aber was soll's. Mein Programm stellt jetzt also zwei Dateilisten zusammen. Die erste Liste beinhaltet die Dateien, die kopiert werden müssen, weil sie im Zielverzeichnis nicht existieren oder weil sie geändert wurden. Und eine Dateiliste mit zu löschenden Dateien, die im Quellverzeichnis nicht mehr existieren. Ergebnis soll sein, dass die Verzeichnisse auf der Festplatte und auf dem USB Stick später identisch sind.

Das Programm befindet sich im Anhang. Bedinung und Ergebnis sollten selbst erklärend sein. "d:\Dokumente" ist bei mir zum Beispiel das Verzeichnis in dem ich arbeite und "I:\eigene Dateien\2005-01-27\Dokumente" wäre mein Backupverzeichnis mit dem ich es synchronisieren will. Am Ende sollen dann beide Ordner "Dokumente" identisch sein.

Version: 0.1.0.1 vom 2005-06-02@0:50
Erste funktionstüchtige Version. Bitte mal testen, ob irgendwelche schwerwiegenden Macken auftreten.

Version: 0.1.0.2 vom 2005-06-02@12:00
Selber einen Bug gefunden.

Version: 1.0.0.1 vom 2005-06-04@00:58
Langsam wird es brauchbar.
Neues Feature: Jobs. Man kann jetzt Abgleiche von Verzeichnissen abspeichern, so das sman nicht immer die passendne Ordner manuell auswählen muss.

Version: 1.2.0.0 vom 2005-06-11@15:10
Multithreading implementiert
TPegasus-Klasse mit Events ausgestattet
Anzeigen der aktuellen Dateinamen in der Statuszeile

Version: 1.3.0.0 vom 2005-06-13@13:16
Nur geänderte Dateien haben jetzt ein orangenes/braunes ( ) Plus

Version: 1.5.0.0 vom 2006-06-24
Skiplist implementiert. Gibt es in der Ini-Datei eine Sektion "SkipList", werden die Ordner und Unterordner in dieser Sektion beim Abgleich ignoriert:
Code:
[Skiplist]
0=D:\Homepage\luckie-online\forum
Jetzt auch mit Sourcecode im Archiv.
Miniaturansicht angehängter Grafiken
pegasus_570.png  
Angehängte Dateien
Dateityp: zip pegasus_117.zip (291,2 KB, 390x aufgerufen)
Ein Teil meines Codes würde euch verunsichern.
 
CG2003

 
Delphi 2009 Professional
 
#81
  Alt 7. Aug 2006, 12:06
Hallo Luckie,

ich habe mal die MD5-Unit von Assarbad gegen die von Matthias Fichtner (www.fichtner.net) ausgetauscht, und entsprechende leichte Änderungen an Deinem Programm vorgenommen.

Aber auch mit dieser Unit bleibt dein Programm "hängen". Bei mir besonders bei Word-Dokumenten (*.doc).

Also denke ich, hat es mit der Erstellung der MD5-Hashes anscheinend nichts zu tun, das Dein Programm "stehen bleibt".
Sebastian M.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

 
Delphi 12 Athens
 
#82
  Alt 7. Aug 2006, 12:26
Duhu Luckie,

hab mir och ma deinen Pegasus angeguckt und irgendwie läuft da was nich so, wie soll bestimmt soll.

Isch kann of die Verzeichnisbuttons rumklicken wie isch will, aber nüschts passiert.


Nagut, also hab'sch ma selber kompiliert, nachgeguckt und siehe da ... CoInitialize(nil) liefet S_FALSE und wenn es dat macht, machst du überhauptnüschts ... nichma 'ne Fehlermeldung hast'e für mich. *eingeschnapptsei*


So läuft es ^^
Delphi-Quellcode:
var
  CoInit: Boolean;
begin
  Result := false;

  CoInit := CoInitialize(nil) = S_OK;
  try
    ...
  finally
    if CoInit then CoUninitialize;
  end;

Hier ma ä leicht verständliches Beispiel:
Delphi-Quellcode:
program Project1;

uses Windows, SysUtils, ActiveX;

var CoInit1, CoInit2: Boolean;

begin
  CoInit1 := CoInitialize(nil) = S_OK;
  try

    CoInit2 := CoInitialize(nil) = S_OK;
    try
      MessageBox(0, PChar('CoInit1=' + BoolToStr(CoInit1, True)
        + ', CoInit2=' + BoolToStr(CoInit2, True)), '', 0);
    finally
      if CoInit2 then CoUninitialize;
    end;

  finally
    if CoInit1 then CoUninitialize;
  end;
end.
Man kann nur einmal initialisieren (jedenfalls bei mir > D7 + WinXP SP2).

Und da es über TApplication.Initialize schonmal aufgerufen wurde ...

Delphi-Quellcode:
procedure TApplication.Initialize;
begin
  if InitProc <> nil then TProcedure(InitProc);
end;
InitProc zeigt auf InitComObj, wo entweder CoInitializeEx oder CoInitialize ofjerufen wird.

Mann ohh mann, da such man sich dumm und dusslig und dann isses da, wo man hätte als erstes nachsehen können/sollen.
Code:
//ComObj.pas ... die von D7
initialization
  ...
  if not IsLibrary then
  begin
    SaveInitProc := InitProc;
    [color=clRed]InitProc := @InitComObj;[/color]
  end;

Und dat hier...
Zitat:
---------------------------
Pegasus.exe - Fehler in Anwendung
---------------------------
Die Ausnahme "Unbekannter Softwarefehler" (0x0eedfade) ist in der Anwendung an der Stelle 0x7c81eb33 aufgetreten.


---------------------------
OK Abbrechen
---------------------------
es macht sich besonders gut, wenn sich (noch) nichts in der ListView1 befindet
Delphi-Quellcode:
procedure TForm1.ListView1DblClick(Sender: TObject);
var
  s: String;
begin
  s := ListView1.Items[Listview1.ItemIndex].Caption;
  ShellExecute(Handle, 'open', PChar(s), nil, nil, SW_SHOWNORMAL);
end;
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#83
  Alt 7. Aug 2006, 12:37
Werde ich mal einpflegen in meiner Version. Danke für deine Mühe.
Michael
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

 
Delphi 12 Athens
 
#84
  Alt 7. Aug 2006, 12:59
Ach ja, hätt ich beinah vergessen ...

du löschst doch alle leeren Ordner?


Na ja, es is zwar nich so schlimm, aber manchma lege ich 'nen Ordner schon an, bevor ich diesen (Tage/Wochen später) mal nutze (befülle).

Tja, diese Ordner würden dann ja von dir gelöscht.
OK, ich könnte den/die dann zwar irgendwann mal wieder neu anlegen (z.B. erst wenn er wirklich benötigt wird).

Eventuell wäre da ein Test ob ein Ordner im Quellverzeichnis vorhanden ist besser, als "nur" nachzusehn ob was in dem Ordner drin ist.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

 
Delphi 12 Athens
 
#85
  Alt 19. Aug 2006, 00:16
Zitat:
So, hab hier mal ein winziges "Linux und Windows, wir mögen uns nicht"-Problem:
(hatte unter Linux 'ne Datei [FAT32] gespeichert und in Windows war die dann ärgerlicher Weise nicht auffindbar ... von der Größe her könnte sie nun wieder aufgetaucht sein, nur daß man sie halt nich lesen kann und sie och noch so'nen netten Datumsfehler enthält, abgesehn von dem komischen Dateinamen)
Zitat:
---------------------------
Pegasus.exe - Fehler in Anwendung
---------------------------
Die Ausnahme "Unbekannter Softwarefehler" (0x0eedfade) ist in der Anwendung an der Stelle 0x7c81eb33 aufgetreten.


---------------------------
OK Abbrechen
---------------------------



---------------------------
Anwendungsfehler
---------------------------
Exception EConvertError in Modul Pegasus.exe bei 00007F8E.

Ungültiges Argument zum Codieren des Datums.


---------------------------
OK
---------------------------



---------------------------
Pegasus.exe - Fehler in Anwendung
---------------------------
Die Ausnahme "Unbekannter Softwarefehler" (0x0eedfade) ist in der Anwendung an der Stelle 0x7c81eb33 aufgetreten.


---------------------------
OK Abbrechen
---------------------------



---------------------------
Anwendungsfehler
---------------------------
Exception EOSError in Modul Pegasus.exe bei 0000D576.

Systemfehler. Code: 5.

Zugriff verweigert.


---------------------------
OK
---------------------------



---------------------------
Pegasus.exe - Fehler in Anwendung
---------------------------
Die Ausnahme "Unbekannter Softwarefehler" (0x0eedfade) ist in der Anwendung an der Stelle 0x7c81eb33 aufgetreten.


---------------------------
OK Abbrechen
---------------------------



---------------------------
Error
---------------------------
Runtime error 217 at 0040D576
---------------------------
OK
---------------------------
Grund siehe Bild.

FileAge lieferte -1 als Ergebnis.

Meine Lösung:
Delphi-Quellcode:
// fill Listview
with Form1 do
begin
  Listview1.Items.BeginUpdate;
  for i := 0 to slNewFiles.Count - 1 do
  begin
    ...
    ListItem.SubItems.Add(Format('%f KB', [GetFileSize(PChar(slNewFiles.Strings[i])) / 1024]));
    try
      Listitem.SubItems.Add(DateTimeToStr(FileDateToDateTime(FileAge(slNewFiles.Strings[i]))));
    except
      Listitem.SubItems.Add('[ERROR]');
    end;
    Listitem.ImageIndex := 1;
  end;
dat dann natrülich och nochma bei den anderen beiden FileAge's in Unit1 ^^

Und dann bricht SHFileOperation die Operation ab, sobald ein Fehler auftritt, also alle nachfolgenden Dateien werden nich kopiert/gelöscht, aber dennoch erfolgreich aus der Liste ausgetragen.
Ich hatte das mal so gelöst, das bei 'nem Fehler dann nochmal die Dateien einzeln verarbeitet wurden, vorallem weil ich keine andere Möglichkeit sah Programmtechnich rauszufinden bei welcher Datei(en) der Fehler auftrat.

z.B.:
Delphi-Quellcode:
Function DeleteToRecycler(Const FileNames: TDynWideStringArray): Boolean;
  Var P: PWideChar;
    i, i2: Integer;
    ShellInfo: TSHFileOpStructW;

  Begin
    Result := False;
    P := nil;
    Try
      i := 0;
      For i2 := High(FileNames) downto 0 do If FileNames[i2] <> 'Then Inc(i, Length(FileNames[i2]) + 1);
      If i = 0 Then Exit;
      P := GetMemE(i * 2 + 4);
      ZeroMem(P, i * 2 + 4);
      For i2 := High(FileNames) downto 0 do If FileNames[i2] <> 'Then Begin
        Dec(i, Length(FileNames[i2]) + 1);
        CopyMem(Pointer(FileNames[i2]), P + i, Length(FileNames[i2]) * 2);
      End;
      ZeroMem(@ShellInfo, SizeOf(TSHFileOpStructA));
      ShellInfo.Func := FO_DELETE;
      ShellInfo.opFrom := P;
      ShellInfo.Flags := FOF_NOCONFIRMATION or FOF_ALLOWUNDO or FOF_NOERRORUI;
      Result := SHFileOperationW(ShellInfo) = S_OK;
    Finally
      FreeMem(Pointer(P));
    End;
    If not Result Then Begin
      Result := True;
      For i := High(FileNames) downto 0 do
        If FileExists(FileNames[i]) Then Begin
          ZeroMem(@ShellInfo, SizeOf(TSHFileOpStructA));
          ShellInfo.Func := FO_DELETE;
          ShellInfo.opFrom := Pointer(FileNames[i]);
          ShellInfo.Flags := FOF_NOCONFIRMATION or FOF_ALLOWUNDO or FOF_NOERRORUI;
          If SHFileOperationW(ShellInfo) <> S_OK Then Result := False;
        End;
    End;
  End;
bei If SHFileOperationW(ShellInfo) <> S_OK Then könnte man sich jetzt noch reinhängen und die Datei(en) ermitteln/speichern...


zum Thema "// create not existing folders":
Zitat von PSDK > SHFILEOPSTRUCT Structure:
Copy and Move operations can specify destination directories that do not exist and the system will attempt to create them. The system normally displays a dialog box to ask the user if they want to create the new directory. To suppress this dialog box and have the directories created silently, set the FOF_NOCONFIRMMKDIR flag in fFlags.
(wäre vorallem unpraktisch, wenn man keine Dateien kopieren ließe, aber die "nötogen" Vereichnisse dennoch erstellt würden)

PS: die Häckchen, welche man vor die Dateinamen (da unten in der Liste) machen kann werden auch irgendwann mal ausgewertet?
(kann die beiden Dateien nicht vom Stick löschen ... Dateisystemfehler ... und auslassen kann ich sie ja auch nicht -.-'' )


Ach ja, weil ich's grad mal versucht hatte ... wie wäre es, wenn man da unten die Dateiliste sortieren könnte, indem man auf die süßen Spltenüberschriften klickt? *hundeblickaufsetz*
so, dat hatte ich vor ein paar Tagen verfaßt, inzwischen weiß ich auch noch, daß ein "ähnlicher" Fehler auftritt, wenn man z.B. eine Datei löscht, nachdem Pegasus die Datei eingelesen hatte, und sie nach dem Löschen anzeigen wollte (weil sie als neu/verändert erkannte ... vor dem Löschen) ... Datei existiert nicht mehr, daher Datumsfehler (-1)
Miniaturansicht angehängter Grafiken
pegasus_953.jpeg  
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#86
  Alt 19. Aug 2006, 02:04
Zu meiner Schand emuss ich gestehen, dass ich noch nicht dazu gekommen bin etwas an dem Programm zu machen.
Michael
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

 
Delphi 12 Athens
 
#87
  Alt 19. Aug 2006, 10:02
och, hat ja Zeit ... hab für mich ja auch erstmal nur'n paar Workarounds eingebaut, dammit es ohne Abzustürzen läuft

ich war ja mehr üb das VCL von dir überrascht
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

 
Delphi 12 Athens
 
#88
  Alt 29. Aug 2006, 11:49
Moin Luckie ^^


erstmal hab ich ein Problem festgestellt, kann aber einfach nicht sagen woher es kommt o.O

und zwar, wenn ich meinen USB-Sick mit einem Verzeichnis auf der Platte synchronisiere, dann läuft erstmal das Erstellen der Dateilist normal ab, auch das Syncronisieren läuft ohne (scheinbar) Probleme durch,
nur wenn dich danach nochmal eine Dateiliste erstelle werden plötzlich wieder Unterschiede gefunden, obwohl doch nach dem Syncronisieren keine mehr vorhanden sein sollten.

Es gab auch keine Fehlermeldung, daß bestimmte Dateien nicht kopiert werden konnten, oder dergleichen.

Auch weiß ich nicht, oder die Dateien beim ersten Durchgang schon in der Dateiliste enthalten waren, oder ob sie schon dort übersehen wurden.


Ist bisher auch nur 2-mal aufgefallen und beim ersten Mal war's erst nach dem 3. Durchlauf alles synchron.
Beim 2. Mal hatte ich wenigstens mit 'nem eigenem (alten) Programm nochmal verglichen und die Unterschiede waren (nach dem 1. Durchlauf) wirklich noch da.

Konnte dieses aber im Debugger bisher noch nicht reproduzieren -.-''

Ach ja:
1 GB USB-Stick
im Durchschnit 500-900 MB mit 17.000-18.000 Dateien



Dann reagiert dein Programm manchmal nicht mehr ... vorwiegend, wenn man auf Abbrechen geklickt hatte und dann eine Weile was anderes machte (also der Pegasus im Hintergrund lag),
danach war dann die ganze Form komplett Weiß und er konnte nur noch über den taskmanager beendet werden.
(wobei dieses auch an meinem Windows liegen könnte ... ist ja etwas lediert, wie man an meinem Problemchen mit EM_SETCUEBANNER sieht -.-'' )




Nun noch ein kleiner Tipp bezüglich der Windows-Cache:
Du ließt die Dateien ja rückwärts ein, demnach würde ich FILE_FLAG_RANDOM_ACCESS bei CreateFile empfehlen.



Und ich weiß ja nicht wieviel du am Pegasus noch ändern willst, aber bei meiner Dateianzahl rechnet der schon echt lange beim Filtern/Anzeigen der Dateiliste (nach dem Suchen/Hashen der Dateien), vorallem wenn sich mal viel verändert hatte.
Ich denk mal ein Großteil dieser Zeit (anzeigen / ListBox füllen) könnte man verhindern, indem die Dateiinfos nich noch ein zweites Mal ausgelesen werden würden. (eventuell gleich bei der Dateisuche mit speichern? ... [size=2]GetFileSize und FileAge ruft ja für jede Datei einzeln nochmals FindFirstFile auf ... GetFileSize ruft FileExists, welches nochmals FileAge aufruft, womit dann pro Datei 3-mal FindFirstFile + die paar mal bei der Dateisuche aufgerufen wird ... dauert halt etwas, wenn die WindowsCache sich dann jedesmal nochmals auf dem langsamen USB-Stick vergewissert, daß sie noch aktuell ist[/size])
Zumindest ein FileExists/FileAge/FindFirstFile kann man leicht einsparren :mrgreen;
Code:
////////////////////////////////////////////////////////////////////////////////
// Procedure : GetFileSize
// Comment  : Returns the filesize

function GetFileSize(szFile: PChar): Int64;
var
  fFile                 : THandle;
  wfd                   : TWIN32FINDDATA;
begin
  result := 0;
  [color=darkred][s]if not FileExists(szFile) then exit;[/s][/color]
  fFile := FindFirstfile(pchar(szFile), wfd);
  if fFile = INVALID_HANDLE_VALUE then exit;
  [color=red]if wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 then[/color]
    result := ([color=blue]Int64(wfd.nFileSizeHigh) shl 32[/color]) or wfd.nFileSizeLow;
  windows.FindClose(fFile);
end;
  Mit Zitat antworten Zitat
XeRo

 
Delphi 7 Enterprise
 
#89
  Alt 29. Aug 2006, 13:29
sieht super aus dein programm.
ist es auch netzwerktauglich?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

 
Delphi 12 Athens
 
#90
  Alt 29. Aug 2006, 15:18
theoretisch ja. (und praktisch vermutlich auch)

Du mußt nur die Ordner so angeben, wenn du es im Explorer machen würdest.
Nur in wieweit es bei geschützten Verzeichnissen geht müßte man testen.

Es geht halt nahezu alles was MSDN-Library durchsuchenFindFirstFile auch kann.

[add2]
MSDN-Library durchsuchenSHFileOperation sollte och mit beachtet werden, aber wenn das die selben Namenskonventionen hat, wie FindFirstFile, dann sollte sogar FTP kein Problem sein ^^


[add]
PS: der Fehler von nkaaa in #44 is och noch drin ... liegt wohl an der fehlenden Synchronisierung
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 9 von 11   « Erste     789 1011      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz