Seite 3 von 3

Verfasst: 26.09.2007 11:58
von Agent
Spielt aber keine Rolle. Die Routine bleibt beim 1. READDATA hängen. Der Callback kommt danach erst.

Verfasst: 26.09.2007 12:09
von HeX0R
Gut, dass du es ohne Callback ausprobiert hast, weil ich wette dann funktioniert es.

Probier es mal mit Prototype anstatt diesem CallFunction-Gepfriemel, welches man eh nicht mehr nehmen sollte.
So in etwa:

Code: Alles auswählen

Prototype MyProgressRoutine(Pos.q, Length.q)

Procedure SK_CopyFile(sourcefile$, targetfile$, OverwriteExistingFile.b=#True, ProgressRoutine.MyProgressRoutine=0, qPackSize.q=0)
 
  ; Definitionen
  Protected qSourceFileLen.q, qSourceFilePos.q
  Protected *CopyBuffer, qDataReaded.q
  Protected lSourceFile.l, lTargetFile.l, lResult.l
  Protected Memory.MEMORYSTATUS

  ; Rückgabe-Codes definieren
  #SK_CopyFile_Failed             = 0 ; #False
  #SK_CopyFile_OK                 = 1 ; #True
  #SK_CopyFile_0ByteFile          = 2 ; Quell-Datei ist 0 Byte groß
  #SK_CopyFile_UserAbort          = -1 ; User hat abgebrochen
  #SK_CopyFile_FileNotFound       = -2 ; Quell-Datei nicht gefunden
  #SK_CopyFile_CannotOpenSource   = -3 ; Konnte Quelle nicht öffnen
  #SK_CopyFile_CannotCreateTarget = -4 ; Konnte Zieldatei nicht anlegen
  #SK_CopyFile_TargetCorrupt      = -5 ; Source-Size und Target-Size sind unterschiedlich. Ggf, Speicher voll.
  #SK_CopyFile_MemoryError        = -6 ; Konnte Speicher nicht reservieren
 
  ; Standard-Wert für Rückgabe: Fehler!
  lResult=#SK_CopyFile_Failed


  ; Progress-Routine (Aufbaubeispiel)
        ; Procedure SK_CopyFile_ProgressCallback(act_pos.q, filesize.q)
        ;   If filesize>0
        ;     percentage_done = (act_pos*100)/filesize
        ;   Else
        ;     percentage_done = 100
        ;   EndIf
        ;   SetGadgetState(#main_progressbar_file, percentage_done)
        ; EndProcedure
 
  ; Gibt es Zieldatei schon: User fragen wie es weiter gehen soll!
  If FileSize(targetfile$)>0 And OverwriteExistingFile=#False ; Ziel existiert, User will gefragt werden!
    If MessageRequester("","Möchten Sie folgende Datei überschreiben?"+#CRLF$+#CRLF$+targetfile$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
      ProcedureReturn #SK_CopyFile_UserAbort
    EndIf     
  EndIf
 
  ; Quelle öffnen
  lSourceFile = OpenFile(#PB_Any, sourcefile$)   
  qSourceFilePos = 0
   
  If IsFile(lSourceFile) ; Quelle öffnen ok?
   
    ; Zieldatei erzeugen
    lTargetFile = CreateFile(#PB_Any, targetfile$)
   
    If IsFile(lTargetFile) ; Ziel öffnen ok?
     
      ; Wieviel arbeit liegt vor uns
      qSourceFileLen=Lof(lSourceFile) ; Dateigröße ermitteln
     
      If qSourceFileLen > 0 ; Quelle eine 0-Byte-Datei?
       
        ; Paketgröße ermitteln
        If qPackSize = 0 ; Dynamische Paketgröße             
          GlobalMemoryStatus_(Memory.MEMORYSTATUS)
          If qSourceFileLen < 3145728 ; 3 MB
            qPackSize = qSourceFileLen
          ElseIf (qSourceFileLen/100) < (Memory\dwAvailPhys / 4)
            qPackSize = qSourceFileLen / 100
          Else
            qPackSize = (Memory\dwAvailPhys / 1000)
          EndIf
        EndIf
       
        ; Falls ProgressCallback: Startwert eintragen, damit User sieht es passiert was
        If ProgressRoutine
          ProgressRoutine(1, qSourceFileLen)
        EndIf

        ; Speicher reservieren für Blocks...
        *CopyBuffer = AllocateMemory(qPackSize)
       
        If *CopyBuffer ; Speicher ok? Dann los!
       
          Repeat
           
            ; Daten aus Quelle einlesen
            qDataReaded = ReadData(lSourceFile, *CopyBuffer, qPackSize)
           
            If qDataReaded > 0 ; Daten korrekt gelesen? Dann ab in die Zieldatei
              WriteData(lTargetFile, *CopyBuffer, qDataReaded)               
              qSourceFilePos + qDataReaded               
            ElseIf qDataReaded = 0 And qSourceFilePos < qSourceFileLen ; Ui, da ging was schief
              lResult = #SK_CopyFile_Failed
            EndIf
         
            ; Progress aktualisieren
            If ProgressRoutine And (qDataReaded > 0) And (qSourceFilePos < qSourceFileLen)
              ProgressRoutine(qSourceFilePos, qSourceFileLen)
            EndIf
           
          Until qSourceFilePos >= qSourceFileLen Or qDataReaded=0 Or bGlobalAbort=#True Or bMainExit=#True
   
          If bGlobalAbort = #True ; Hat User abgebrochen?
            lResult = #SK_CopyFile_UserAbort
          EndIf
         
          If qSourceFileLen <> qSourceFilePos ; Gibts Probleme mit den Dateigrößen? Differenzen?
            lResult = #SK_CopyFile_TargetCorrupt
            Debug "Source <> Target"
          EndIf
                     
          ; Speicher wieder freigeben!
          FreeMemory(*CopyBuffer)
         
        Else
          lResult = #SK_CopyFile_MemoryError ; Probleme beim Speicher reservieren
        EndIf
       
      Else
        lResult = #SK_CopyFile_0ByteFile ; War ne 0-Byte-Datei
      EndIf
     
      ; Zieldatei wieder schließen
      CloseFile(lTargetFile)

    Else
      lResult = #SK_CopyFile_CannotCreateTarget ; Zieldatei konnte nicht angelegt werden
    EndIf
   
    ; Quelldatei wieder schließen
    CloseFile(lSourceFile)     
         
    ; Datum und Attribute wie Originaldatei setzen
    SetFileDate(targetfile$, #PB_Date_Created, AddDate(GetFileDate(sourcefile$, #PB_Date_Created), #PB_Date_Hour, UTC_Korrektur))
    SetFileDate(targetfile$, #PB_Date_Modified, AddDate(GetFileDate(sourcefile$, #PB_Date_Modified), #PB_Date_Hour, UTC_Korrektur) )     
    SetFileAttributes(targetfile$, GetFileAttributes(sourcefile$)) ; Attribute angleichen

    ; Progress lieber nochmal auf 100% setzen
    If ProgressRoutine
      ProgressRoutine(qSourceFileLen, qSourceFileLen)
    EndIf
       
    lResult = #SK_CopyFile_OK ; Super, alles ok
  Else
 
    lResult = #SK_CopyFile_CannotOpenSource ; Quelle konnte nicht geöffnet werden :(
  EndIf
   
  ProcedureReturn lResult
EndProcedure

Verfasst: 26.09.2007 13:36
von Agent
Was soll das ändern? Es liegt wohl eindeutig am ReadData() oder?

Verfasst: 26.09.2007 13:51
von HeX0R
Agent hat geschrieben:Was soll das ändern? Es liegt wohl eindeutig am ReadData() oder?
Nein liegt es nicht!
Aber ist mir jetzt auch wurscht.

Kleiner Tipp am Rande noch auch wenns bei dir bestimmt nicht ankommt:
CallFunctionFast kann nicht mit QUADs als Parameter umgehen (steht sogar in der Hilfe).

Verfasst: 26.09.2007 19:58
von Agent
Also gut.
Ich bin dabei auf Prototypes umzustellen. Grundsätzlich läuft die Sache. @HeXOR: Danke.

Bei der Adressierung hab ich wohl noch einen Denkfehler:

ich möchte die Callback-Procedure flexibel angeben können, da die Kopierroutine eine Include-Datei ist. Nun folgendes:

Definition wie folgt:

Code: Alles auswählen

Prototype.l SK_CopyFile_ProgessCallback(act_pos.q, filesize.q)
Das der Aufbau der Kopierroutine. Hier ist *ProgressCallback zu sehen.

Code: Alles auswählen

Procedure SK_CopyFile(sourcefile$, targetfile$, *ProgressCallback.l=0, OverwriteExistingFile.b=#True, lBufferSize.l=#False)

CopyFile_Progess.SK_CopyFile_ProgessCallback = @*ProgressCallback

...

EndProcedure
PB meldet beim Kompilen keinen Fehler, aber beim Ausführen ein
Invalid memory access
Aufgerufen habe ich die Kopierroutine wie folgt:

Code: Alles auswählen

copysuccess.b=SK_CopyFile(CopyList()\entryname$, targetfile$, @SK_CopyFile_ProgressCallback())
Kann mir jemand auf die Sprünge helfen mit der Adressierung?
Mit einer CallFunctionFast() ging das so. Bei Prototypes wohl nicht mehr.

Vielen Dank im vorraus!

Verfasst: 26.09.2007 20:58
von HeX0R
O.k., ich hab wahrscheinlich eine masochistische Ader... ;)

Da du bereits die Adresse deiner Prozedur übergibst, wäre es so richtig:

Code: Alles auswählen

CopyFile_Progess.SK_CopyFile_ProgessCallback = *ProgressCallback
Mit @*ProgressCallback würdest du die Adresse deiner ProgressCallback-Variable bekommen, was dich ja bestimmt nicht wirklich interessiert.

Allerdings sehe ich den tieferen Sinn nicht, wieso machst du es nicht wie ich oben (oder hast du meinen Code etwa nicht einmal genauer angeschaut ? *ts ts ts*) ?
Wozu die Adresse nochmal weiterreichen, wenn du sie doch gleich in die richtige Pseudotyp-Variable Bild kannst ?

Re: Probleme mit eigener Kopierroutine

Verfasst: 30.12.2015 02:30
von schleicher
Das hier ist zwar schon sehr alt, aber ich würde es gern nutzen, da diese Kopierfunktion mit Progress_Anzeige ist.
Wie müsste dann der Kopierbefehl aussehen ? So?

Code: Alles auswählen

SK_CopyFile(sourcefile$, targetfile$, 1, 1, 1)
Ganz verstehe ich nicht, wie die Progressbar den akt.Pos. _ Wert bekommt, denn mit

Code: Alles auswählen

Prototype MyProgressRoutine(Pos.q, Length.q)
kann ich als Anfänger nicht so richtig was anfangen Übergibt Prototype die Werte automatisch an die Procedure SK_CopyFile_ProgressCallback(act_pos.q, filesize.q) ?
(Die Procedure : SK_CopyFile_ProgressCallback(act_pos.q, filesize.q) habe ich erstellt so wie es im Beispiel angegeben war.