Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Datei für Schreibzuriffe sperren? (https://www.delphipraxis.net/848-datei-fuer-schreibzuriffe-sperren.html)

thomasdrewermann 16. Sep 2002 07:41


Datei für Schreibzuriffe sperren?
 
Hi,
ist euch bestimmt auch schon passiert, das der sagt, die Datei wird gerade benutzt, löschen/umbennen/speichern nicht möglich!

Wie öffne ich eine Datei so, dass man sie nicht löschen und speichern kann?


MFG
Thomas

Daniel 16. Sep 2002 08:08

Hallo,

wenn Du die Datei mit AssignFile/Reset/Close bearbeitest, dann solltest Du Dir mal in der Delphi-Hilfe die verschiedenen Werte der Variablen "FileMode" ansehen. Damit kannst Du steuern, in welchem Modus (nur lesen / nur schreiben / exklusiv etc.) Du eine Datei öffnen möchtest.

Wenn Du mit der API-Funktion "CreateFile" arbeitest, dann findest Du die entsprechenden Paramater in der MSDN-Library :: CreateFile().

thomasdrewermann 16. Sep 2002 21:40

Wie gebe ich eine mit
Code:
tfilestream.create('DATEI',fmshareexclusive);
wieder frei?
ich meine nicht in der selben procedure, sondern an einer anderen stelle im PROGRAMM, gibts da ne möglichkeit. Die variabele ist lokal für die eine Procedure deklariert.

MFG
Thomas

Christian Seehase 16. Sep 2002 21:51

Moin Thomas,

die Variable ist ja eingentlich nur ein Pointer auf das Filestream Objekt.
Wenn Du jetzt ein public Feld in einem Formular anlegst, oder eine globale Variable vom Typ TFileStream, dann kannst Du in dieser lokalen Prozedur diesen Pointer in die globale Variable übergeben, und an jeder beliebigen Stelle im Programm darauf zugreifen, und dass natürlich mit jeder beliebigen Methode.
Nur: Dieses Verfahren wäre, gelinde gesagt, nicht besonders sauber.

Mir fallen dazu zwei Fragen ein:
  1. Warum muss die FileStream Variable lokal deklariert sein?
  2. In welchem Zusammenhang brauchst Du den FileStream? Vielleicht gibt's ja eine andere Lösung.

thomasdrewermann 16. Sep 2002 21:59

Mir gings nur darum den Dateizuriff für andere anwendungen zu sperren, aber ich will zu laufzeit dateien sperren und entsperren können.

Christian Seehase 16. Sep 2002 22:12

Moin Thomas,

dann bietet es sich doch an, ein Objekt zu erstellen, das ein variables Array enthält, welches Einträge für Dateipfad und entsprechenden TFileStream speichert, und das mit Methoden versehen ist, die es einem ermöglichen übergebene Dateien über fmShareExclusive zu sperren, bzw. durch Freigeben eines Eintrags im array (anschliessendes komprimieren des Arrays eventuell einplanen) wieder zur Verfügung zu stellen.

thomasdrewermann 16. Sep 2002 22:14

Kannst du die Deklaration eines solchen variabelen Arrays in Code-Form posten??Ich davon nämlich 0 Ahnung.

MFG
Thomas

Christian Seehase 16. Sep 2002 22:27

Moin Thomas,

ich hab' da mal eben was zusammengeschrieben, wie ich mir das so ungefähr vorstelle. Ist natürlich nicht getestet, aber probiers mal aus, bzw. schau's Dir mal an.

Code:
[b]type[/b]
  TcsFileLockEntry =
    [b]packed[/b] [b]record[/b]
      sFilePath : [b]string[/b];
      fsFile   : TFileStream;
    [b]end[/b];

  TcsFileLocker = [b]class[/b](TObject)
  [b]private[/b]
    FaFilelist : [b]array[/b] [b]of[/b] TcsFileLockEntry;
  [b]public[/b]
    [b]constructor[/b] Create;
    [b]destructor[/b] Destroy; override;
    [b]procedure[/b] LockFile([b]const[/b] p_sFilePath : [b]string[/b]);
    [b]procedure[/b] UnlockFile([b]const[/b] p_sFilePath : [b]string[/b]);
  [b]end[/b];

[b]implementation[/b]

[color=#000080]{$R *.DFM}[/color]



[color=#000080]{ TcsFileLocker }[/color]

[b]constructor[/b] TcsFileLocker.Create;
[b]begin[/b]
  [b]inherited[/b] Create;
  [color=#000080]// Nur der Ordung halber, eigentlich nicht notwendig[/color]
  SetLength(FaFileList,0);
[b]end[/b];

[b]destructor[/b] TcsFileLocker.Destroy;

[b]var[/b]
  i : integer;

[b]begin[/b]
  [b]for[/b] i := 0 [b]to[/b] High(FaFileList) [b]do[/b]
  [b]begin[/b]
    FreeAndNil(FaFileList[i].fsFile);
  [b]end[/b];
  SetLength(FaFileList,0);
  [b]inherited[/b] Destroy;
[b]end[/b];

[b]procedure[/b] TcsFileLocker.LockFile([b]const[/b] p_sFilePath: [b]string[/b]);
[b]begin[/b]
  [color=#000080]// Neuen Eintrag erzeugen[/color]
  SetLength(FaFileList,Length(FaFileList)+1);
  FaFileList[High(FaFileList)].sFilePath := p_sFilePath;
  FaFileList[High(FaFileList)].fsFile   := TFileStream.Create(p_sFilePath,fmShareExclusive);
[b]end[/b];

[b]procedure[/b] TcsFileLocker.UnlockFile([b]const[/b] p_sFilePath: [b]string[/b]);

[b]var[/b]
  i       : integer;
  iDeleted : integer;

[b]begin[/b]
  iDeleted := -1;
  [b]for[/b] i := 0 [b]to[/b] High(FaFileList) [b]do[/b]
  [b]begin[/b]
    [b]if[/b] FaFileList[i].sFilePath = p_sFilePath [b]then[/b]
    [b]begin[/b]
      FreeAndNil(FaFileList[i].fsFile);
      iDeleted := i;
      break;
    [b]end[/b];
  [b]end[/b];
  [b]if[/b] iDeleted > -1 [b]then[/b]
  [b]begin[/b]
    [b]for[/b] i := iDeleted+1 [b]to[/b] High(FaFileList) [b]do[/b]
    [b]begin[/b]
      FaFileList[i-1] := FaFileList[i];
    [b]end[/b];
    SetLength(FaFileList,Length(FaFileList)-1);
  [b]end[/b];
[b]end[/b];

thomasdrewermann 16. Sep 2002 22:38

ich hab die sache in eine unit gesetzt und hab ein progr geschrieben, das wie folgt aussieht:
Code:
procedure TForm1.Button1Click(Sender: TObject);
var i:tcsfilelocker;
begin
i:=tcsfilelocker.Create;
i.LockFile(edit1.text);
i.free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var i:tcsfilelocker;
begin
i:=tcsfilelocker.Create;
i.unLockFile(edit1.text);
i.free;
end;
Hab ich was falsch gemacht`??

Man kann die Datei trtzdem noch öffnen und ausführen!

MFG
Thomas

thomasdrewermann 16. Sep 2002 22:48

ich habs raus :-))
Ups wie peinlich, :oops: da bekommt man einen mundgerechten Code, und man ist zu doof ihn einzubinden :-) :mrgreen:.

VIELEN DANK an Christian DANKE :mrgreen: :bounce1: :bouncing4:

Christian Seehase 16. Sep 2002 22:55

Moin Thomas,

bitte gerne. :D

Um kurz auf die Positionierung der Variablen die vom Typ TcsFileLocker ist zu kommen:

Zum einen eignet sie sich wohl als Eigenschaft des Hauptformulares, so dass das Objekt dann im OnCreate des Formulares erzeugt, und im OnDestroy wieder freigegeben werden kann, oder aber als globale Variable. Erzeugt und wieder freigegeben wird es dann im initialization/finalization Abschnitt der Unit, in der die Variable deklariert wird.

Christian Seehase 19. Sep 2002 14:09

Moin Thomas,

ich wusste doch, dass ich was vergessen hatte :?

Beim speichern eines Dateipfades
statt:
Code:
FaFileList[High(FaFileList)].sFilePath := p_sFilePath;
besser
Code:
FaFileList[High(FaFileList)].sFilePath := AnsiUpperCase(p_sFilePath);

und beim Suchen
statt:
Code:
if FaFileList[i].sFilePath = p_sFilePath then
besser
Code:
if FaFileList[i].sFilePath = AnsiUpperCase(p_sFilePath) then
Sollte sich mal die Schreibweise der Datei geändert haben, würdest Du sie ansonsten nicht finden.

BTW:
Durch diese Methode Dateien zu sperren, kann es bei einer grossen Anzahl von Dateien, gerade unter Win 98, dazu kommen, dass dem System die Dateihandles ausgehen. Allerdings gehe ich mal nicht davon aus, dass Du so viele Dateien sperren willst, als dass sich dieser Umstand hier auswirken könnte.

thomasdrewermann 19. Sep 2002 21:45

Jo, ich werde es ändern!


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:24 Uhr.

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