[gelöst]LoadFromFile vom netzlaufwerk

Alle Fragen zur Netzwerkkommunikation
Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

[gelöst]LoadFromFile vom netzlaufwerk

Beitrag von gladio »

Ich habe ein Problem beim Öffnen von Dateien von Netzlaufwerken deshalb stelle ich das mal hier ein.

Windows 7 und 10, Lazarus 1.6x und 1.8RC3

Über eine FileListBox wird eine Datei ausgewählt, geöffnet und in einem Memo angezeigt.

Code: Alles auswählen

var 
    str2: TStringList;
begin
  ..
  Arbeitsverzeichnis := INIDat.ReadString('Arbeitspfad','Pfad','C:\ ');
  FileListBox1.Directory := Arbeitsverzeichnis;
  Datei := extractFilename(FileListBox1.FileName);
  ...
  Str2 := TStringList.Create;
  try
    Str2.LoadFromFile(Datei)//bricht hier ab und springt zu ..free
    Memo1.Text := STr2.Text;
  ...
  finally
    Str2.Free;
  end;
....
 


Funktioniert auch wunderbar, solange sich die Datei nicht in einem Netzlaufwerk auf dem Datenserver oder eines NAS oder in einem Cloude-Verzeichnis befinden.
Dann wird mit dieser allseits bekannten Fehlermeldung abgebrochen:

Code: Alles auswählen

 
Unable to open file ...
Press OK to ignore...
Press cancel to kill ...

Bei OK passiert nichts, bei Cancel wird das Programm beendet.

Die zu öffnenden Dateien stammen aus einem Auslesegerät.
Sie werden vom gleichen Benutzer (Admin-Rechte) mit dem ich das Programm ausführe, abgelegt.
Es gibt keine Zugriffsbeschränkungen bei den Dateien, werden ja auch nur gelesen.
Das Programm selbst mit höchsten Rechten zu compilieren oder als Admin auszuführen bringt nichts.
Kopiere ich die Dateien vom Netzlaufwerk auf ein lokales Verzeichnis, lassen sie sich problemlos öffnen/lesen.

Prakmatisch könnte ich das lösen, indem ich die zu öffnende Datei einfach temporär ins lokale Programmverzeichnis mit CopyFile kopiere,
lese und dann wieder lösche.

Aber warum geht das nicht direkt auf dem Netzlaufwerk?
Zuletzt geändert von gladio am So 27. Aug 2017, 10:06, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: LoadFromFile vom netzlaufwerk

Beitrag von wp_xyz »

Hast du das Netzlaufwerk so ins System eingebunden, dass es einen Laufwerksbuchstaben hat ("Netzlaufwerk verbinden")? Wenn ja, dann sollte es funktionieren. Ich habe es eben mit meinem NAS getestet.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: LoadFromFile vom netzlaufwerk

Beitrag von af0815 »

wp_xyz hat geschrieben:Hast du das Netzlaufwerk so ins System eingebunden, dass es einen Laufwerksbuchstaben hat ("Netzlaufwerk verbinden")? Wenn ja, dann sollte es funktionieren. Ich habe es eben mit meinem NAS getestet.

Ich habe festgestellt, das NAS (meist samba) nicht gleich Microsoft Server sind. Die beste Erfahrung habe ich damit gemacht, wenn das Share als Laufwerk gemountet ist UND aktiv ist. Es passiert öfters, wenn die Verbindung nicht aktiv ist, das der Explorer sich zwar verbinden kann, du aber von der programmierseite keine (einfache + automatische) Möglichkeit hast das Laufwerk zu aktivieren.

Beim testen würde ich parallel den Explorer offen halten und kontrollieren ob die Verbindung/Share noch wirklich aktiv ist.

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: LoadFromFile vom netzlaufwerk

Beitrag von braunbär »

Ja, das kann ich bestätigen. Das Problem tritt aber auch bei freigegebenen Windows Netzlaufwerken sporadisch auf (bei einem Windows Server ist es mir noch nicht passiert).
Die Verbindung zwischen Windows und einem Netzlaufwerk reißt manchmal unmotiviert ab, oder wird beim Start gar nicht erst hergestellt. Erst wenn man mit dem Explorer (oder einem anderen brauchbaren Dateimanager) das Laufwerk anwählt, funktioniert es. Ich habe auch noch nicht herausgefunden, was man vom Programm aus machen kann, um in so einem Fall das Laufwerk wieder zu aktivieren. Ich habe mich aber noch nicht ernsthaft bemüht, wahrscheinlich würde schon ein Shell-Aufruf des Windows Explorer mit einem Netzverzeichnis als Parameter als Workaround funktionieren.

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: LoadFromFile vom netzlaufwerk

Beitrag von gladio »

Die betreffenden Laufwerke sind eingebunden und haben Laufwerksbuchstaben.
Die zu öffnenden Dateien lassen sich auch problemlos mit dem Windows Editor oder WordPad oder LibreOffice öffnen.

Ich habe auch mal das kopieren erfolgreich ausprobiert:

Code: Alles auswählen

CopyFile(Arbeitsverzeichnis+'\ '+Datei, 'c:\test\'+Datei);

Wahrscheinlich werde ich das dann auch so umsetzen, daß ich die Datei erst lokal kopiere und dann mit der Kopie arbeite.

Daß sich freigegebene Netzlaufwerke unter Windows nach einer gewissen/unbestimmten Zeit bei Nichtnutzung 'schlafen legen'
habe ich auch schon beobachtet.
Ist aber nicht relevant, weil ich den Exploren meistens offen hatte.

Mathias
Beiträge: 6167
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: LoadFromFile vom netzlaufwerk

Beitrag von Mathias »

oder wird beim Start gar nicht erst hergestellt. Erst wenn man mit dem Explorer (oder einem anderen brauchbaren Dateimanager) das Laufwerk anwählt, funktioniert es. Ich habe auch noch nicht herausgefunden,

Als ich noch mit Windows arbeitete ist mir dies auch schon mehrmals aufgefallen. :roll:

Ich habe auch mal das kopieren erfolgreich ausprobiert:

Code: Alles auswählen

CopyFile(Arbeitsverzeichnis+'\ '+Datei, 'c:\test'+Datei);

Da staune ich, das dies geklappt hat, da du hinter dem '\' ein Leerzeichen hast.

Die betreffenden Laufwerke sind eingebunden und haben Laufwerksbuchstaben.
Die zu öffnenden Dateien lassen sich auch problemlos mit dem Windows Editor oder WordPad oder LibreOffice öffnen.

Ich kann es mir schlecht vorstellen, aber evtl. liegt es an gross und klein-Schreibung.
Sind evtl. Umlaute im Dateinamen ?

Code: Alles auswählen

 Str2.LoadFromFile(Datei)//bricht hier ab und springt zu ..free

Was kommt bei Showmessage(Datei); ?

Code: Alles auswählen

Datei := extractFilename(FileListBox1.FileName);

Was passiert, wen du das extractFileName weglässt ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: LoadFromFile vom netzlaufwerk

Beitrag von gladio »

[quote="Mathias"]Da staune ich, das dies geklappt hat, da du hinter dem '\' ein Leerzeichen hast.[quote]

Das Leezeichen habe ich hier nur zusätzlich in den Code eingefügt. Du hast sicher schon bemerkt das bei der Code-hervorhebung ...'\'... der Backslash nicht angezeigt wird.


Groß-/Kleinschreibung und Umlaute spielen keine Rolle, da Pfad und Daieiname ausgewählt und nicht eingegebne werden.

ShowMessage(Datei) zeigt den Dateinamen der ausgewählten Datei, so wie es sein soll.
Aber auch nur, wenn ExtractFileName nicht weggelassen wird.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: LoadFromFile vom netzlaufwerk

Beitrag von wp_xyz »

gladio hat geschrieben:Ich habe auch mal das kopieren erfolgreich ausprobiert:

Code: Alles auswählen

CopyFile(Arbeitsverzeichnis+'\ '+Datei, 'c:\test\'+Datei);

Wahrscheinlich werde ich das dann auch so umsetzen, daß ich die Datei erst lokal kopiere und dann mit der Kopie arbeite.

Seltsam, eigentlich wird da doch auch nur die Datei geöffnet und gelesen, so wie in der TStringList. Vielleicht kommt der FileStream, der von TStringList geöffnet wird, nicht damit zurecht, dass die Datei nicht sofort offen ist? Könntest du mal direkt mit einem Filestream arbeiten und nach dem Öffnen eine kleine Verzögerung einbauen?

Code: Alles auswählen

var
  fs: TFileStream;
 
  Arbeitsverzeichnis := INIDat.ReadString('Arbeitspfad','Pfad','C:\ ');
  FileListBox1.Directory := Arbeitsverzeichnis;
  Datei := extractFilename(FileListBox1.FileName);
  ...
  Str2 := TStringList.Create;
  try
    fs := TFileStream.Create(Datei, fmOpenRead + fmShareDenyNone);
    try
      Sleep(1000)// ganz brutal 1 Sekunde warten - nur zum Test...
      Str2.LoadfromStream(fs);
    finally
      fs.Free;
    end;
    Memo1.Text := STr2.Text;
  ...
  finally
    Str2.Free;
  end;

Wenn es geht, könntest du schrittweise die Verzögerung in Sleep() verringern.

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: LoadFromFile vom netzlaufwerk

Beitrag von gladio »

hm, schade.
jetzt spingt es von

Code: Alles auswählen

fs := TFileStream.Create(Datei, fmOpenRead + fmShareDenyNone);

zum äußeren

Code: Alles auswählen

  finally
       Str2.Free;

und bricht ab.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: LoadFromFile vom netzlaufwerk

Beitrag von wp_xyz »

Dann probier mal ein FileExists vor dem Öffnen des Streams oder vor StringList.LoadFromFile - irgendwas muss bei Copy anders sein, damit es dort funktioniert:

Code: Alles auswählen

  Str2 := TStringList.Create;
  try
    if not FileExists(Datei) then Sleep(1000)// <------- neu
    Str2.LoadFromFile(Datei);
    Memo1.Text := STr2.Text;
  ...
  finally
    Str2.Free;
  end;

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: LoadFromFile vom netzlaufwerk

Beitrag von MacWomble »

gladio hat geschrieben:Das Leezeichen habe ich hier nur zusätzlich in den Code eingefügt. Du hast sicher schon bemerkt das bei der Code-hervorhebung ...'\'... der Backslash nicht angezeigt wird.


Es wäre auch besser, grundsätzlich die folgende Schreibweise zu wählen:

Code: Alles auswählen

CopyFile(Arbeitsverzeichnis + PathDelim + Datei);
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: LoadFromFile vom netzlaufwerk

Beitrag von gladio »

Jetzt wird Sleep(1000) ausgeführt, also existiert 'Datei' an dieser Stelle für das Programm unverständlicherweise nicht.

Datei und Arbeitsverzeichnis sind als normaler String definiert.

Aber ein

Code: Alles auswählen

ShowMessage(Arbeitsverzeichnis+[Backslash]+Datei);

zeigt alles korrekt an.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: LoadFromFile vom netzlaufwerk

Beitrag von wp_xyz »

Es muss mit einem Delay zu tun haben. In CopyFile passiert z.B. folgendes

Code: Alles auswählen

  TryCount := 0;
  While TryCount <> 3 Do Begin
    SrcHandle := LazFileUtils.FileOpenUTF8(SrcFilename, fmOpenRead or fmShareDenyWrite);
    if (THandle(SrcHandle)=feInvalidHandle) then Begin
      Inc(TryCount);
      Sleep(10);
    End
    Else Begin
      TryCount := 0;
      Break;
    End;
  End;
  If TryCount > 0 Then
  begin
    if ExceptionOnError then
      raise EFOpenError.CreateFmt({SFOpenError}'Unable to open file "%s"', [SrcFilename])
    else
      exit;
  end;

Das heißt: Es gibt drei Versuche, die Datei zu öffnen. Schlägt einer fehl, wird 10 ms gewartet und dann neu vesucht.

Andererseits macht der Constructor des TFileStream nur 1 Versuch:

Code: Alles auswählen

constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
 
begin
  FFileName:=AFileName;
  If (Mode and fmCreate) > 0 then
    FHandle:=FileCreate(AFileName,Mode,Rights)
  else
    FHAndle:=FileOpen(AFileName,Mode);
 
  If (THandle(FHandle)=feInvalidHandle) then
    If Mode=fmcreate then
      raise EFCreateError.createfmt(SFCreateError,[AFileName])
    else
      raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
end;

Wenn du dir nun einen neuen Stream von TFileStream ableitest, bei dem diese drei Versuche und die kurze Verzögerung der Prozedur Copy in den Constructor eingebaut sind, müsste es doch gehen!
Zuletzt geändert von wp_xyz am Fr 25. Aug 2017, 21:48, insgesamt 1-mal geändert.

Mathias
Beiträge: 6167
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: LoadFromFile vom netzlaufwerk

Beitrag von Mathias »

Code: Alles auswählen

Datei := extractFilename(FileListBox1.FileName);

Was für ein Zweck erfüllt das "extractFileName" im ersten Post?

Wie sollte das LoadFromFile funktionieren, wen man die Pfad-Angabe weglöscht ?
Ausgenommen das Programm wurde im gleichen Ordner gestartet, bei welchem sich auch "Datei" befindet.
Oder man wechselt den Ordner mit "chdir".
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: LoadFromFile vom netzlaufwerk

Beitrag von gladio »

Der Code aus dem ersten Post ist etwas zusammengestückelt.
Datei := extractFilename(FileListBox1.FileName);
steht eigentlich im OnClick von FileListBox.
Damit weise ich der String-Variablen 'Datei' den Dateinamen der aus der FileListe ausgewählten Datei zu.

Der Pfad dazu steht in der String-Variablen 'Arbeitsverzeichnis'.
Das Arbeitsverzeichnis wird aus einer Ini-datei ausgelesen und an die FileListBox übergeben.

Das passt so.
Ich arbeite gern mit aussagekräftigen Variablen. Das hält den Code leichter lesbar.

Antworten