Zielpfad prüfen...

10. Mai 2007 09:33

Hallo,

ein Report wird in unserer Datenbank beim Aufruf per SAVEASHTML gespeichert.

Jetzt würde ich gerne vorher prüfen, ob der Zielpfad existiert bzw. erreichbar ist und wenn nicht einen alternativen Pfad angeben.

Ich habe mich schon an dem Befehl: EXISTS versucht, aber der prüft, ob eine Datei existiert und nicht ein Pfad. Und eine Testdatei als Workaround würde hier nicht funktionieren, weil das Verzeichnins zwischenzeitlich immer wieder geleert wird.

Habt Ihr eine Idee, wie sich das lösen lässt?

Danke im voraus.

10. Mai 2007 09:39

Du könntest die Testdatei als Hidden, System und Schreibgeschützt markieren, wer sie dann trotzdem löscht, bekommt ne Abmahnung ;-)
Wenn Du NTFS-Rechte einsetzen kannst, dann mach die Berechtigungen für "Jeder=nur lesen" und alle anderen Berechtigungen entfernen, dann kann sie gar nicht gelöscht werden, ohne dass jemand explizit die Berechtigungen wieder erteilt.

10. Mai 2007 09:57

es gibt da die versteckte (nicht sichtbare) Tabelle File im Navision. Dort kann auf das Feld Path ein Filter gesetzt werden mit der Pfadabgabe.
Wenn der Pfad verfügbar ist, dann ist der Count auf diese Tabelle größer 0.
Ich hoffe das hilft dir weiter.

10. Mai 2007 10:05

tba hat geschrieben:es gibt da die versteckte (nicht sichtbare) Tabelle File im Navision. Dort kann auf das Feld Path ein Filter gesetzt werden mit der Pfadabgabe.
Wenn der Pfad verfügbar ist, dann ist der Count auf diese Tabelle größer 0.
Ich hoffe das hilft dir weiter.

Hierbei muss man aber darauf achten, dass man vor dem Zugriff zur Prüfung die Recordvariable für diese Tabelle cleared, da sonst alte Informationen enthalten sind!

10. Mai 2007 10:18

wieso? nach einem neuen Setrange, liefert mir der Count doch ein aktuelles Ergebnis?

10. Mai 2007 10:36

nur, wenn du zwischendurch einen anderen Pfad auswählst, solange der gleichbleibt, ändert sich nichts.

10. Mai 2007 10:55

Wenn der Pfad gleich bleibt, dann ist auch das Verzeichnis nachwievor nicht da. (was ja dieser Check erreichen soll)
Aber Du hast natürlich echt, ein Clear mehr oder weniger stört natürlich niemals. :-)

10. Mai 2007 11:23

Hallo,

schau mal hier, ich hatte das Problem, das ab und an das Verzeichnis nicht zu finden war, da die Tabelle FILE mir einen streich gespielt hatte.

Merkwürdiges Verhalten der Tabelle FILE
EIN CLEAR wird vermutlich nicht ausreichen!
Gruß Mikka

10. Mai 2007 12:06

Stimmt, Mikka hat recht, ein Clear allein reicht nicht.
Also nach dem CLear zuerst auf einen anderen Pfad und dann erst auf den gewünschten Pfad....

Du kannst natürlich auch einfach nach jeder Aktion, die den Pfad prüft, Navision einmal schließen und neustarten ;-)

10. Mai 2007 12:09

tba hat geschrieben:[...]
Wenn der Pfad verfügbar ist, dann ist der Count auf diese Tabelle größer 0. [...]

Wenn euer Server und euer Netzwerk zu schnell sein sollte, könnt ihr gerne einen File.COUNT verwenden, um herauszufinden, ob das Verzeichnis exisitert.
Wer jedoch seine System- und Netzwerkressourcen schonen möchte, der verwendet einfach
Code:
IF File.ISEMPTY THEN
  HoleAlternativesVerzeichnis;

Alternativ kann auch folgendes verwendet werden
Code:
IF NOT File.FIND('-') THEN
  [...]

10. Mai 2007 12:27

Ersteinmal vielen Dank für Eure Hilfe.

Im Prinzip funktioniert das mit der Tabelle: File, aber, egal welchen Code ich benutze:

Code:
recFile.RESET;
recFile.SETRANGE(Path,'F:\');
IF recFile.ISEMPTY THEN
...


oder

Code:
recFile.RESET;
recFile.SETRANGE(Path,'F:\');
IF recFile.find('-') THEN
...


Wenn es keinen Zugriff auf den Pfad gibt, dann erscheint immer die Fehlermeldung: "Das Betriebssystem findet den Pfad nicht...".
Das hat dann zur Folge, dass das Ganze stehen bleibt, bis jemand die Fehlermeldung mit OK bestätigt hat. Das ist bei einem automatischen Nachtlauf, welchem noch weitere folgen sollten, recht hinderlich.

Wie kann ich die Fehlermeldung vermeiden?

10. Mai 2007 13:45

Genau um diese Fehlermeldung ging es auch bei mir Damals, ich bin Wahnsinnig geworden (der Fehler trat nicht immer auf, aber meistens Abends nach Feierabend!)

Hier ein Auszug von useren Code.
Zunächst ein Reset, dann SETRANGE und ein FIND.
Dann erst ein SETRANGE auf dein Wunschverzeichnis, so sollte es klappen!
Code:
IF Einlesen THEN BEGIN
  TTSEinr.TESTFIELD("Verz. offen");    // Prüfen, ist der Pfad in der Einrichtungstabelle
  TTSEinr.TESTFIELD("Verz. erledigt");   // Prüfen, ist der Pfad in der Einrichtungstabelle
  Verzeichnis.RESET;
  Verzeichnis.SETRANGE(Verzeichnis.Path,TTSEinr."erz. erledigt"); // 001 MR 1x in ein anders Verz. wechseln
  IF Verzeichnis.FIND('-') THEN;                                                  // damit dder Path erkannt wird!
  Verzeichnis.SETRANGE(Path,TTSEinr."Verz. offen");
  Verzeichnis.SETRANGE("Is a file",TRUE);
  Verzeichnis.SETFILTER(Name,'*.DAT|*.dat');
...


Gruß Mikka

10. Mai 2007 16:12

@ Mikka

Und was machst Du, wenn der Dein Pfad: "Verz. erledigt" nicht erreichbar ist? Dann kommt doch auch die Fehlermeldung beim FIND('-').

Ich möchte, dass wenn der eine Pfad nicht erreichbar ist (weil keine Berechtigung, Laufwerk nicht gefunden, entsprechender Server nicht erreichbar,...), dass ein anderer Pfad genommen wird. Also muss ich den ersten Pfad prüfen, ob er aktuell erreichbar ist. Wenn er es nicht ist, soll der andere Pfad genommen werden, aber bitte ohne Fehlermeldung... :wink:

Mein Test sieht derzeit so aus:

Code:
Speicherverzeichnis := 'G:\';
recFile.RESET;
recFile.SETRANGE(Path,Speicherverzeichnis);
IF recFile.FIND('-') THEN   [color=blue]--> Hier erfolgt die Fehlermeldung, wenn Pfad nicht erreichbar![/color] 
  REPORT.SAVEASHTML(REPORT::Test1,
                  Speicherverzeichnis + 'Testfile' + FORMAT(TODAY) + '.html')
ELSE BEGIN
  Speicherverzeichnis := 'C:\';
  REPORT.SAVEASHTML(REPORT::Test1,
                  Speicherverzeichnis + 'Testfile' + FORMAT(TODAY) + '.html');
END;

10. Mai 2007 18:11

warum schreibst du dann nicht direkt in das alternative Verzeichnis und rufst anschließend eine Batchdatei mit dem Shell-Befehl auf, in dem mit dem Dos-Befehl Rename die Datei auf den "unsicheren" Pfad verschoben wird? Wenn der Rename-Befehl dann einen Fehler wirft, sollte Navision das nicht weiter stören.

Alternative wäre eine Codeunit, in deren OnRun-Trigger die Prüfung erfolgt, die nur dann einen Rückgabewert von True liefert, wenn der Test erfolgreich war. Ich habe allerdings nicht geprüft, ob damit dieser Fehler auch abgefangen werden kann.
Ich verwende diesen Trick erfolgreich beim Importieren von Rechnungen aus Altsystemen. Ich frage den Rückgabewert der Codeunit zum Verbuchen der Rechnung ab und schreibe bei Misserfolg eine Fehlermeldung in eine Protokolldatei und mache automatisch mit der nächsten weiter:

Code:
  COMMIT;
  IF NOT SalesPost.RUN(SalesHeader) THEN BEGIN
    outtext:='Die Rechnung ' + SalesHeader."Posting No." + ' konnte nicht gebucht werden.';
    write2file();
  END;

Ich habe zum Teil 20000 Rechnungen in einer XML-Datei und selbst wenn mal eine von den nicht verbucht werden kann, läuft der Import weiter. Vielleicht hilft Dir der Trick bei Deinem Problem auch weiter.

11. Mai 2007 09:11

NavHummel hat geschrieben:Und was machst Du, wenn der Dein Pfad: "Verz. erledigt" nicht erreichbar ist? Dann kommt doch auch die Fehlermeldung beim FIND('-').


Dann mach ich Feierabend :-P
Nein, spass beiseite.

In meinen Fall würde ich irgend ein Verzeichniss nehmen, das es gibt z.B. 'C:\'
Da es in Deinem Fall nicht geht, ist Schumis Vorschlag nicht schlecht.
(Evtl. schon, ich bin mir nicht sicher!)

Der Fehler entsteht nicht bei Zugriff auf die Tabelle FILE, sondern wenn der Report gestartet wird, da der angegebene Pfad nicht existiert!
Mir fällt auf, das du nicht den Tabellenfeldern arbeitest z.B. reFile.Path sondern mit deiner Variable "Speicherverzeichnis.
(das würde ich ändern, sonst "knallt" es immer)
Dadurch, das der FIND Befehl mit einem IF abgefangen wird,
kommt hier keine Fehlermeldung. (Wenn kein Verzeichnis da ist)

Bei Deinem Code vermisse ich das wechseln des Verzeichnisses vorab,
ungefähr so:
Code:
Speicherverzeichnis := 'G:\temp';         // In irgendein Verzeichnis wechseln
recFile.RESET;

IF recFile.FIND('-') THEN;                // Beachte das Semikolon!
Speicherverzeichnis := 'G:\';             // Jetzt das richtige Verz.
recFile.SETRANGE(Path,Speicherverzeichnis);
IF recFile.FIND('-') THEN   [color=blue]--> Hier erfolgt die Fehlermeldung, wenn Pfad nicht erreichbar![/color]
  REPORT.SAVEASHTML(REPORT::Test1,
                  Speicherverzeichnis + 'Testfile' + FORMAT(TODAY) + '.html')
ELSE BEGIN
  Speicherverzeichnis := 'C:\';
  REPORT.SAVEASHTML(REPORT::Test1,
                  Speicherverzeichnis + 'Testfile' + FORMAT(TODAY) + '.html');
END;


Durch das geziehlte wechseln, wird die Tabelle FILE aktualisiert bzw. neu eingelesen.
Wenn du dann wieder in anderen Pfad wechselst, kannst du in der Tabelle das entsprechende Verzeichnis sehen oder nicht.

***
Ich habe mir Damals eine Testfom mit der Tabele FILE gemacht und ein paar Buttons, die unterschiedliche Filder ausführen.
Auf diesen Weg konnte ich das "Ding" besser Verstehen lernen :-)

Hier mein Code, mit etwas mehr Details:
Code:
F Einlesen THEN BEGIN
  TTSEinr.TESTFIELD("Verz. offen");    // Prüfen, ist der Pfad in der Einrichtungstabelle
  TTSEinr.TESTFIELD("Verz. erledigt");   // Prüfen, ist der Pfad in der Einrichtungstabelle
  Verzeichnis.RESET;
  Verzeichnis.SETRANGE(Verzeichnis.Path,TTSEinr."erz. erledigt"); // 001 MR 1x in ein anders Verz. wechseln
  IF Verzeichnis.FIND('-') THEN;                                                  // damit dder Path erkannt wird!
  Verzeichnis.SETRANGE(Path,TTSEinr."Verz. offen");
  Verzeichnis.SETRANGE("Is a file",TRUE);
  Verzeichnis.SETFILTER(Name,'*.DAT|*.dat');
  TempVerz.DELETEALL;                   
  IF Verzeichnis.FIND('-') THEN
    REPEAT
    TempVerz.INIT;
    TempVerz.Path := Verzeichnis.Path;
    TempVerz.Filename := Verzeichnis.Name;
    IF NOT TempVerzeichnis.INSERT THEN
      TempVerzeichnis.MODIFY;
  UNTIL Verzeichnis.NEXT = 0;
  // SLEEP(10000);                // War mal wegen des Verzeichnis-Fehlers!
  IF TempVerz.FIND('-') THEN REPEAT
    CLEAR(TopLinkEinlesen);
    MeinDataPort.FILENAME(TempVerz.Path + TempVerz.Filename);
      MeinDataPort.RUNMODAL;
      COMMIT;
...

Bei mir werden die Verzeichnisse und Dateinamen in eine Temp.Tabelle geschrieben, da ich viele Dateien einlesen will.
***

Ich hoffe ich konnte mit den Ausführungen dir weiterhelfen?
Gruß Mikka

16. Mai 2007 09:30

Gibt es hier wirklich ein Problem?
NavHummel hat geschrieben:Wenn es keinen Zugriff auf den Pfad gibt, dann erscheint immer die Fehlermeldung: "Das Betriebssystem findet den Pfad nicht...".
Das hat dann zur Folge, dass das Ganze stehen bleibt, bis jemand die Fehlermeldung mit OK bestätigt hat. Das ist bei einem automatischen Nachtlauf, welchem noch weitere folgen sollten, recht hinderlich.


wenn das ganze in einem Nachtlauf funktionieren soll, dann kann man ja wahrscheinlich davon ausgehen. dass da ein Objektaufrufplaner läuft. Und für diese eine Maschine kann man sehr wohl im Vorfeld sicherstellen, das die Pfade auch existieren.

Zitat in [qoute] Tags abgelegt, wg. der besseren Lesbarkeit.
[code] Tags sind für Programmcode, bitte dieses beachten!
Gruß Mikka

16. Mai 2007 10:46

ich habe das ganze mit einem Automationserver gelöst
Code:

Name     DataType     Subtype                                          Length
Folder   Automation   'Microsoft Scripting Runtime'.FileSystemObject   
IF CREATE(Folder) THEN;
IF NOT Folder.FolderExists(V_Pfad) THEN BEGIN
   Folder.CreateFolder(V_Pfad);
END;


Michael
Zuletzt geändert von mespelage am 4. März 2009 17:12, insgesamt 2-mal geändert.

16. Mai 2007 10:52

tba hat geschrieben:nd für diese eine Maschine kann man sehr wohl im Vorfeld sicherstellen, das die Pfade auch existieren.


Wenn das sichergestellt ist, sollte es kein Problem darstellen!

@mespelange
Ich habe es zwar nicht getestet, aber eine elegante Lösung, wenn es nur um die Verzeichnisprüfung geht.
Gruß Mikka

Re: Zielpfad prüfen...

4. März 2009 10:26

@Timo, ich fände es schön, wenn du in dein Codeunit FileManagement diese Funktion(en) FolderExists und/oder PathExists aufnehmen würdest.

Und bitte helft mir:
Bei Validierung eines eingegebenen Pfades möchte ich prüfen, ob der Pfad existiert.

verkürzt:
Pfad - OnValidate
Code:
IF Pfad[STRLEN(Pfad)] <> '\' THEN
  Pfad += '\';

RecFile.RESET;
CLEAR(RecFile);
RecFile.SETRANGE(Path, Pfad); 
IF RecFile.ISEMPTY THEN
  ERROR('%1 existiert nicht', Pfad);


Öffne ich die Form zu diesem Feld neu und trage eine ungültigen Pfad ein (z.B. 'D\'), so erhalte ich:
Das Betriebssystem findet den Pfad nicht, den Sie für die Datei C:\Dokumente und Einstellungen\Benutzername\D\*.* eingegeben haben.
Prüfen Sie bitte das aktuelle Laufwerk und Verzeichnis und prüfen Sie auch die Schreibweise des Pfadnamens.


Erst im Anschluss kommt 'D\ existiert nicht.'.
Wiederhole ich das Spiel, ohne die Form zu schließen, kommt nur noch MEINE Fehlermeldung.
Schließe ich die Form und gebe nun wieder einen falschen Pfad an, kommt wieder diese zusätzliche, automatische Fehlermeldung.

Wie kommt diese auf den Pfad meiner eigenen Dateien und wie kann ich diese Meldung unterdrücken? Was habe ich falsch gemacht?

Re: Zielpfad prüfen...

4. März 2009 14:07

Natalie hat geschrieben:@Timo, ich fände es schön, wenn du in dein Codeunit FileManagement diese Funktion(en) FolderExists und/oder PathExists aufnehmen würdest.

In meiner aktuellen Version existiert bereits die Funktion FolderExists(Foldername : Text[256]) : Boolean.
Ich sollte vielleicht mal die Codeunits hier aktualisieren ;-)

Re: Zielpfad prüfen...

4. März 2009 16:52

Die Prüfung kannst du ebenfalls mit der automation lösen.
siehe mein Beitrag vom 16.Mai 2008

mfg Michael