Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Dateigröße auf Netzlaufwerk ermitteln (https://www.delphipraxis.net/104333-dateigroesse-auf-netzlaufwerk-ermitteln.html)

himitsu 2. Dez 2007 01:28

Re: Dateigröße auf Netzlaufwerk ermitteln
 
wie groß ist denn die Datei?
Delphi-Quellcode:
function GetFileSize2(const FileName: String): Int64;
var
  H: THandle;
  D: TWIN32FindDataW;

begin
  H := FindFirstFileW(PWideChar(FileName), D);
  If H = INVALID_HANDLE_VALUE then exit; //GetLastError_auswerten;
  result := (Int64(d.nFileSizeHigh)*(MAXDWORD + 1))+d.nFileSizeLow;
  CloseHandle(H);
end;
PS: * und + sind etwas langsam/unoptimal
und bevor du versuchst einen Integer/Cardinal [d.nFileSizeHigh] (also 4 Byte) auf einen Int64 (8 Byte) zu erweitern, mußt die dessen Größe erstmal ändern (Int64)
Delphi-Quellcode:
Function GetFileSizeA(Const FileName: String): Int64;
  Var FileNameW: WideString;
    H: THandle;
    D: TWIN32FindDataW;

  Begin
    Result := -1;
    FileName := FileNameW;
    H := FindFirstFileW(PWideChar(FileName), D);
    If H = INVALID_HANDLE_VALUE Then Exit;
    If D.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 Then
      Result := (Int64(D.nFileSizeHigh) shl 32) or D.nFileSizeLow;
    CloseHandle(H);
  End;
oder
Delphi-Quellcode:
Function GetFileSizeA(Const FileName: String): Integer;
  Var FileNameW: WideString;
    H: THandle;
    D: TWIN32FindDataW;

Begin
    Result := -1;
    FileName := FileNameW;
    H := FindFirstFileW(PWideChar(FileName), D);
    If H = INVALID_HANDLE_VALUE Then Exit;
    If (D.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0)
      and (D.nFileSizeHigh = 0) and (D.nFileSizeLow < $80000000) Then
      Result := D.nFileSizeLow;
    CloseHandle(H);
  End;
PSS: was micht wundert ist, daß bei PWideChar(FileName) nicht gemeckert wird, vonwegen AnsiString-PWideChar-Konvertierung :shock:

haentschman 2. Dez 2007 01:30

Re: Dateigröße auf Netzlaufwerk ermitteln
 
... 1.07 MB oder 1.122.304 Byte

himitsu 2. Dez 2007 01:32

Re: Dateigröße auf Netzlaufwerk ermitteln
 
hmmm, 1 MB paßt ja locker in einen Integer :gruebel: ,
was kommt denn raus?

Zitat:

PSS: was micht wundert ist, daß bei PWideChar(FileName) nicht gemeckert wird, vonwegen AnsiString-PWideChar-Konvertierung Shocked

haentschman 2. Dez 2007 01:35

Re: Dateigröße auf Netzlaufwerk ermitteln
 
... 3.04 MB

PS: alles was du so als Lösungen hast mögen funktionieren...wenn ich die Details verstehen würde wäre es besser... :oops:

haentschman 2. Dez 2007 06:45

Re: Dateigröße auf Netzlaufwerk ermitteln
 
...Guten Morgen alle... :hi:

...das hat mir alle keine Ruhe gelassen.

...inzwischen habe ich durch Zufall herausgefunden das mit folgendem Code
Delphi-Quellcode:
function GetFileSize2(const FileName: String): Integer;
var
  H: THandle;
  D: TWIN32FindDataW;

begin
  H := FindFirstFileW(PWideChar(FileName),D);
  If H <> INVALID_HANDLE_VALUE then exit; //GetLastError_auswerten;
  result := (d.nFileSizeHigh*(MAXDWORD))- d.nFileSizeLow;
  CloseHandle(H);
end;
das Ergebnis immer gleich ist...(unterschiedliche Dateien/FileName) ! -5.41 MB... obwohl die kpl. Prozedur durchlaufen wird.

Warnung: Rückgabewert der Funktion könnte undefiniert sein... damit hat Delphi Recht !? :???:

[edit]
ich habe mit Set8087ControlWord($133F) den Gleitkommaüberlauf während der Ausführung meines Programmes ausgeschaltet.
...hat das in diesem Zusammenhang eine Relevanz ? ... Suche nach Strohhalm... :roll:
[/edit]

haentschman 2. Dez 2007 09:20

Re: Dateigröße auf Netzlaufwerk ermitteln
 
...mich wundert gar nichts mehr. :roll:

...die gleichen Probleme mit:

DeleteFile('\\localhost\system\tmp\avdb.fdb');

FileExists('\\localhost\system\tmp\avdb.fdb');

:wall:

...Kann es wirklich sein, das diese Funktionen nicht mit Netzwerk umgehen können ? :gruebel:

himitsu 2. Dez 2007 10:41

Re: Dateigröße auf Netzlaufwerk ermitteln
 
Zitat:

Zitat von haentschman
...inzwischen habe ich durch Zufall herausgefunden das mit folgendem Code
Delphi-Quellcode:
function GetFileSize2(const FileName: String): Integer;
var
  H: THandle;
  D: TWIN32FindDataW;

begin
  H := FindFirstFileW(PWideChar(FileName),D);
  If H = INVALID_HANDLE_VALUE then exit; //GetLastError_auswerten;
  result := (d.nFileSizeHigh*(MAXDWORD))- d.nFileSizeLow;
  CloseHandle(H);
end;
das Ergebnis immer gleich ist...(unterschiedliche Dateien/FileName) ! -5.41 MB... obwohl die kpl. Prozedur durchlaufen wird.



Warnung: Rückgabewert der Funktion könnte undefiniert sein... damit hat Delphi Recht !? :???:

Zur Warnug: da mit dem Aifruf von Exit die Funktion verlassen wird, muß vorher in Rückgabewert gesetzt werden.

Also entweder am Anfang mit initialisieren:
Delphi-Quellcode:
H := FindFirstFileW(PWideChar(FileName),D);
If H = INVALID_HANDLE_VALUE then exit; //GetLastError_auswerten;
result := ...
Oder beim Verlassen der Funktion setzen:
Delphi-Quellcode:
Result := Standard-/Fehlerwert;
H := FindFirstFileW(PWideChar(FileName),D);
If H = INVALID_HANDLE_VALUE then begin
  Result := Standard-/Fehlerwert;
  exit;
end;
result := ...
Zitat:

Zitat von haentschman
ich habe mit Set8087ControlWord($133F) den Gleitkommaüberlauf während der Ausführung meines Programmes ausgeschaltet.
...hat das in diesem Zusammenhang eine Relevanz ?

Da hier ja keine Gleitkommafunktion benötigt werden, sollte es eigentlich egal sein :gruebel:
du könntest da auch höchstens versuchen Set8087ControlWord vorm Aufruf dieser Funktion zurück und nachher dann wiederauf $133F zu setzen.


Delphi-Quellcode:
result := (Int64(d.nFileSizeHigh)*(MAXDWORD + 1))+d.nFileSizeLow;
Int64(d.nFileSizeHigh) > in einen Int64 konvertieren, damit auch Platz für das Vergrößern des Wertes vorhanden ist.
*(MAXDWORD+1) > MAXDWORD ist nur $FFFFFFFF, aber damit der Wert in das Höherwertige LongWord verschoben wird, muß mit $0000000100000000 multiplizert werden,
oder einfach die Bits des Wertes um 32 Bit (LongWord) nach oben verschieben
> Int64(d.nFileSizeHigh) shl 32

Delphi-Quellcode:
Function GetFileSizeA(Const FileName: String): Int64;
  Var FileNameW: WideString;
    H: THandle;
    D: TWIN32FindDataW;

  Begin
    Result := -1; // Fehlerwert setzen (damit bei EXIT ein Wert gesetzt wurde)
    FileName := FileNameW; // Dateiname von String/Ansitring nach WideString übersetzen
    H := FindFirstFileW(PWideChar(FileName), D); // Datei suchen
    If H = INVALID_HANDLE_VALUE Then Exit; // im Fehlerfalls Funktion verlassen
    If D.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 Then // prüfen ob kein Verzeichnis
      Result := (Int64(D.nFileSizeHigh) shl 32) or D.nFileSizeLow; // wenn Datei, dann Result neu setzen
      // Int64(D.nFileSizeHigh) shl 32 > wandelt nFileSizeHigh in einen Int64 um
      //    und verschiebt dessen Wert in das HiLongWord
      // or D.nFileSizeLow > fügt nFileSizeLow in das Regebnis als LoLongWord ein
    CloseHandle(H); // Suche schließen (wenn H = INVALID_HANDLE_VALUE, dann wurde sie nicht geöffnet)
  End;
oder
Delphi-Quellcode:
Function GetFileSizeA(Const FileName: String): Integer;
  Var FileNameW: WideString;
    H: THandle;
    D: TWIN32FindDataW;

Begin
    Result := -1; // Fehlerwert setzen (damit bei EXIT ein Wert gesetzt wurde)
    FileName := FileNameW; // Dateiname von String/Ansitring nach WideString übersetzen
    H := FindFirstFileW(PWideChar(FileName), D); // Datei suchen
    If H = INVALID_HANDLE_VALUE Then Exit; // im Fehlerfalls Funktion verlassen
    If (D.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0) // prüfen ob kein Verzeichnis
      and (D.nFileSizeHigh = 0) and (D.nFileSizeLow < $80000000) Then // prüfen ob die Größe in einen Integer reinpaßt
      Result := D.nFileSizeLow; // Ergebnis setzen (nur als Integer)
    CloseHandle(H); // Suche schließen (wenn H = INVALID_HANDLE_VALUE, dann wurde sie nicht geöffnet)
  End;
PWideChar(FileName) > die Funktion FindFirstFileW braucht eine Referenz auf einen UnicodeString
und dafür muß FileName auch schon in Unicode, also als WideString vorliegen.


und wenn du den String direkt übergiebst? (ohne Variable)
Delphi-Quellcode:
if not DeleteFileW('\\localhost\system\tmp\avdb.fdb') then
  irgendwas := GetLastError;

himitsu 2. Dez 2007 11:01

Re: Dateigröße auf Netzlaufwerk ermitteln
 
hab hier eben mal ein Laufwerk freigegeben und

bei DeleteFileW('\\localhost\D:\test.dat');
kommt das raus 83 = Der Netzwerkpfad wurde nicht gefunden.

bei DeleteFileW('\\localhost\Daten\test.dat');
kommt 82 = Verbindung wurde nicht hergestellt, weil ein identischer Name bereits im Netzwerk vorhanden ist. Wählen Sie "System" in der Systemsteuerung, um den Computernamen zu ändern, und versuchen Sie es erneut. raus

schon komisch, vorallem letzere Meldung versteh ich da irgendwie nicht ... ist doch schön, wenn es
vorhanden ist :gruebel:

[add]
DeleteFileW('\\myPC\Daten\test.dat'); hat die Datei übrigend erfolgreich gelöscht :-D

thkerkmann 2. Dez 2007 11:15

Re: Dateigröße auf Netzlaufwerk ermitteln
 
Hi,

also deine Probleme kann ich überhaupt nicht nachvollziehen

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    edFilename: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  sr: tSearchrec;
  ierr: integer;
begin
  Memo1.Clear;
  ierr := FindFirst(edFilename.text, faAnyfile - faDirectory, sr);
  while ierr = 0 do
  begin
    if (sr.name <> '.') and (sr.name <> '..') then
    begin
      Memo1.Lines.Add(sr.name + ': sr.size=' + IntToStr(sr.size)
        + ', w32finddata.size='
        + IntToStr(int64(sr.FindData.nFileSizeHigh) shl 32
        + sr.FindData.nFileSizeLow));
    end;
    ierr := FindNext(sr);
  end;
  FindClose(sr);
end;

end.
Werf mal ein TEdit ein TMemo und einen TButton auf ein Form.
Nenn das TEdit edFilename (warum ich das umbenannt hab, keine Ahnung) :-D

Dann kannst du im Editfeld deinen Pfad eingeben, und auf den Button klicken, das Memo zeigt das Inhaltsverzeichnis mit den Dateigrößen aus dem Searchrecord und aus den Finddata.

Ich hab das bei mir getestet und das funktioniert einwandfrei.

Endweder ist deine Freigabe keine Freigabe, oder du hast keine Rechte auf dieser Freigabe. Das würde ich dann mal mit einem einfachen Dir in der Dos-Box testen.
Mit \\localhost\ geht das nicht, das ist aber auch klar, da dein Rechner ja nicht localhost heist. Gib den lokalen Rechnernamen an, dann geht das wieder. Und nebenbei: der Laufwerksbuchstabe hat in einem UNC Pfad gar nix zu suchen.

Gruss

Christian Seehase 2. Dez 2007 11:38

Re: Dateigröße auf Netzlaufwerk ermitteln
 
Moin Himitsu,

[quote)="himitsu"]bei DeleteFileW('\\localhost\D:\test.dat');
kommt das raus 83 = Der Netzwerkpfad wurde nicht gefunden. [/quote]

Logisch, denn in dem Beispiel müsste die Freigabe D: lauten.
Wenn Du eine UNC-Angabe machst, musst Du den Freigabenamen angeben, was im Falle von Laufwerk D: standardmässig D$ wäre (falls nicht jemand die administrativen Freigaben abgeschaltet hat.


Noch was allgemeines:
Ich stosse hier immer wieder auf die Zeile:

Delphi-Quellcode:
if H <> INVALID_HANDLE_VALUE then exit;
Das sollte wohl besser
Delphi-Quellcode:
if H = INVALID_HANDLE_VALUE then exit;
heissen ;-)
Sonst wird die Funktion immer verlassen, wenn ein gültiges Handle ermittelt wurde, und das Handle wird nicht wieder freigegeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:59 Uhr.
Seite 3 von 4     123 4      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz