Schreibschutz auf W2K3 Server

Sonstiges (nicht kategorisierbar)

Moderator: Moderatoren

Antworten
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Schreibschutz auf W2K3 Server

Beitrag von Manfred »

Hi,

ich habe derzeit ein interessantes Phänomen. Ich habe mich gewundert, dass auf einem W2003 Server immer die Fehlermeldung unbekannter Alias kam. Es liegt daran, das die DBF Tabellen in dem Verzeichnis schreibgeschützt liegen. Was mich aber noch mehr verwundert, ist die Tatsache, dass es keine Fehlermeldung beim Öffnen der DBF gibt, obwohl sie in einem Begin Sequence liegt.

Also habe ich ein wenig probiert. In der Sicherheit, das Recht auf Schreiben gegeben, alles klappt wieder. Schreibrecht wieder weggenommen, dafür aber die DBF ReadOnly geöffnet klappt auch.

Jetzt habe ich mir überlegt, wie ich sowas abfangen kann. Also auch bei mir Sambaserver, bzw. auf lokaler Platte unter WinXP jeweils Schreiben deaktiviert um dann im Debugger zu sehen, was denn da passiert. Und siehe da, jetzt kommt eine Fehlermeldung, das die DBF nicht geöffnet werden kann. Genau so, wie ich es erwarten würde. Was ist denn auf einem W2003 Server anders, dass so etwas passieren kann?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von brandelh »

Hallo Manfred,

wie fragst du denn ab ob use erfolgreich war ?

neterr() :!:

BEGIN SEQUENCE ist dafür nicht gedacht und wird dir kein fehlgeschlagenes USE melden !

Wenn eine DBF schreibgeschützt ist, kannst du sie bestenfalls mit use ... READONLY öffnen.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von Tom »

Wenn der ErrorBlock überlagert ist, schlägt das Standard-Errorhandling fehl, also wird auch die Fehlersituation nicht abgefangen, die die Get-/Set-Funktion "NetErr()" mit ".T." antworten lässt. In diesem Fall erzeugt eine Sharing Violation eben auch einen Laufzeitfehler. Dasselbe erlebt man z.B. mit Xb2.Net, da der HTTPErrorHandler von Boris standardmäßig nicht "oError:OsCode = 32 .and. oError:CanDefault" abfängt (böse Falle übrigens :wink: ). Da man vor einer Sequence üblicherweise genau das macht, also den ErrorBlock überlagert, wundert es kaum, wenn dort dann ein Laufzeitfehler erzeugt wird. Im Standard-Errorhandling (ERRORSYS.PRG) wird sonst diese Situation geprüft, NetErr() wird auf ".T." gesetzt und das Fehlersystem beendet sich wieder. Einfach mal in den Code der (ggf. selbst gestrickten) Errorsys schauen!
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von brandelh »

Tom hat geschrieben:Wenn der ErrorBlock überlagert ist, schlägt das Standard-Errorhandling fehl
du meinst es ist abgeschaltet ;-)
Tom hat geschrieben:Get-/Set-Funktion "NetErr()"
Was soll "Get-/Set-Funktion" heißen, es gilt schon seit Clipper, dass man nach USE zwingend NETERR() abfragen muss !

Und in der "normalen" ErrorSys.PRG findet man keinen Eintrag zu NetErr(), also frage ich mich was du meinst :?:
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von Tom »

NetErr() ist eine Get-/Set-Funktion. Das bedeutet: Man kann sie mit einem Parameter (.T. oder .F.) aufrufen, sie speichert diesen Wert (das ist der "Set"-Teil der Funktion). Wenn man sie danach ohne Parameter aufruft, gibt sie den zuletzt gesetzten Wert zurück (das ist der "Get"-Teil). Du kannst NetErr(.T.) einfach selbst setzen, wenn Du Lust hast. Wenn Du danach dann eine Datei öffnest, ohne dass der Laufzeitfehler mit dem OS-Code 32 (Sharing Violation) auftritt, liefert die danach folgende Abfrage von NetErr() trotzdem .T. zurück. Get-/Set-Funktionen sind sehr hilfreich, um nur innerhalb eines Applikationslaufes gültige Parameter zu speichern und abzurufen. Aber es ist eben nicht so, dass NetErr() irgendwie prüft, ob eine Sharing Violation eintrat. Sie wird nur anschließend gesetzt. Ich zitiere die Doku zu NetErr():

Falls bei einem dieser Befehle ein Fehler auftritt, entsteht ein Laufzeitfehler, der durch die Standard-Fehlerbehandlungsroutine in Xbase++ behoben wird. In dieser Routine wird NetErr(.T.) aufgerufen.

Wenn man nun die Standard-Fehlerbehandlungsroutine stoppt, wird von dieser natürlich auch nicht mehr NetErr(.T.) aufgerufen. Damit behält NetErr() den zuletzt zugewiesenen Wert, und der ist sehr wahrscheinlich .F. - und außerdem ensteht ein Laufzeitfehler.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von brandelh »

Da hatte ich wohl zu sehr das GET System gedacht ;-) klar ist es eine Get/Set Funktion ... :-)

Dennoch ist genau NETERR() die Lösung für Manfreds Problem, denn - wenn ich nicht wieder was überlesen habe -
hat er es unterlassen nach USE den Zustand von NETERR() abzufragen und das darf man nicht bei gesharten Dateien.

Die Stelle im ErrorHandler habe ich auch gefunden ...

Code: Alles auswählen

   /* Fehler beim Öffnen einer Datei im Netzwerk */
   CASE oError:genCode == XPP_ERR_OPEN  .AND. ;
        oError:osCode  == 32            .AND. ;
        oError:canDefault                      
      RETURN(.F.)
wenn ER dieses Standardverhalten abgeändert hat ODER selbst NETERR() setzt, muss er natürlich das überprüfen.
Wenn er eXpress++ einsetzt (keine Ahnung) könnte es auch dort geändert worden sein ... dann muss man dort auch in der Doku nachsehen.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von Tom »

In den Standard-Errorsys.PRG früherer Xbase++-Versionen (vor 1.8 oder 1.7, ich weiß es nicht mehr genau) war das explizite Setzen von NetErr() auch noch enthalten, aber vermutlich haben so viele Programmierer daran herumgemurkst, dass Alaska das irgendwann gekapselt hat.

eXpress++ hat keine eigene ErrorSys, aber wenn man den Dot-Prompt oder DC_Interpret() benutzt hat, bleibt bisweilen das interne Fehlerbehandlungssystem "hängen" (jedenfalls bis Build 254).

Whatsoever, wenn man im Rahmen einer Sequence das Fehlersystem ausgehebelt hat, kann NetErr() auch nicht mehr feuern. Dann müsste man innerhalb der Sequence der Fehler direkt abgefangen werden. Oder im Anschluss der Sequence durch ein simples "Used()" auf der Workarea, in der man die geöffnete Datei erwartet.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Schreibschutz auf W2K3 Server

Beitrag von brandelh »

Manfred hat geschrieben:Was mich aber noch mehr verwundert, ist die Tatsache, dass es keine Fehlermeldung beim Öffnen der DBF gibt, obwohl sie in einem Begin Sequence liegt.
Clipper/Xbase++ Standardverhalten, WENN es den Fehler beheben kann (CANDEFAULT), dann wird NETERR() auf .t. gesetzt,
das muss man im Quellcode abfragen und selbst entsprechend reagieren !
Manfred hat geschrieben: In der Sicherheit, das Recht auf Schreiben gegeben, alles klappt wieder.
Schreibrecht wieder weggenommen, dafür aber die DBF ReadOnly geöffnet klappt auch.
logisch, standardmäßig wird shared (Xbase++, sonst exclusive) geöffnet, das braucht schreibzugriff !
Wenn man readonly offnet kann es nur bei exclusive geöffneten Dateien Probleme geben.
Manfred hat geschrieben: Und siehe da, jetzt kommt eine Fehlermeldung, das die DBF nicht geöffnet werden kann.
Genau so, wie ich es erwarten würde. Was ist denn auf einem W2003 Server anders, dass so etwas passieren kann?
Es könnte natürlich sein, dass ein anderer Wert zurückgeliefert (OS-Err oder CANDEFAULT) wird, aber ich konnte noch
nie einen Unterschied feststellen. Vermutlich fragt der Debugger intern nach neterr() und gibt eine Fehlermeldung,
oder der Code ist unterschiedlich !
Tom hat geschrieben:Whatsoever, wenn man im Rahmen einer Sequence das Fehlersystem ausgehebelt hat,
jetzt verstehe ich unsere unterschiedlichen Sichtweisen.

Du gehst davon aus, dass Manfred ein eigenes Errorsystem mit begin sequence und Error-Objekt gesetzt hat:

Code: Alles auswählen

bSaveError := ErrorBlock() 
ErrorBlock( {|e| Break(e)} ) 
BEGIN SEQUENCE      
   ...
RECOVER USING oError 
      ErrorBlock( bSaveError ) 
      IF oError:osCode == ... // Zurück zu BEGIN SEQUENCE 
          ...
      ENDIF 
END SEQUENCE 
ErrorBlock( bSaveError )         
Ich denke er hat eher so etwas und da wird die Standardfehlerbehandlung nicht abgeschaltet.

Code: Alles auswählen

// sowas kann nicht funktionieren, bitte bei NETERR() nachlesen warum :-)
BEGIN SEQUENCE 
   use xyz
RECOVER
   ? "Fehlermeldung Datei kann nicht geöffnet werden!"
END SEQUENCE 
Mal sehen, was er wirklich hat ;-)

PS: Append Blank() braucht auch NetErr()
Gruß
Hubert
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Re: Schreibschutz auf W2K3 Server

Beitrag von Manfred »

Ich habe sowas hier

Code: Alles auswählen

********************************************************************************
METHOD datenbank:oeffnedatenbank(lShared, lInaDb, lReadonly, lSperren, lNewArea)
       LOCAL bSaveError := ErrorBlock( {|e|BREAK(e)})
       LOCAL cFileName  := ::cPfad + ::cDbank + ::cSuffix                       // Zusammenbau des kompletten Pfades mit Namen
       LOCAL nVersuche  := 0
       LOCAL oError

       MEMVAR oSysPara

       DEFAULT lShared   TO .T.                                                 // von Hause aus wird jede DB im Multiuserbetrieb geöffnet, also Shared
       DEFAULT lInaDb    TO .T.
       DEFAULT lReadOnly TO .F.
       DEFAULT lSperren  TO .F.
       DEFAULT lNewArea  TO .T.

       ::erzeugeVerzeichnisse(::cPfad)                                          // dann sind wir immer auf der sicheren Seite (16.08.2010)
       DO WHILE .T.
          ErrorBlock( {|e| BREAK(e)})                                           // was passiert hier??                                                              .
          BEGIN SEQUENCE                                                        // hiermit werden kontrolliert Fehlermeldungen abgehandelt                          .
                DbUseArea(lNewArea, ::cDbe, cFileName, ::cAlias, lShared, lReadOnly) // Öffnungsversuch der Datenbank                                               .
                ::nArea := Select()                                             // es wird sich grundsätzlich der Selectbereich gemerkt, in dem die DB geöffnet wurde
                ::nRecordMenge := (::nArea)->(Reccount())                       // für irgendwelche Zwecke wird sich die aktuelle menge gemerkt                     .
                IF Empty(::cAlias)                                              // es wurde kein Alias vorgegeben                                                   .
                   ::cAlias := (::nArea)->(Alias())                             // also gibt es den Standardnamen                                                   .
                ENDIF
                IF lInaDb
                   AAdd(::aDb, {self,NIL})                                      // 1.Objekt für DB 2.NIL weil man auch den führenden Index angeben kann
                ENDIF
                IF lSperren
                   ::db_sperren("Die DB: " + Upper(::cDbank) + " kann nicht gelockt werden.")
                ENDIF
                IF (::nArea)->(RecSize()) * (::nArea)->(Lastrec()) + (::nArea)->(Header()) + 1 > KRITISCHE_GROESSE_DB
                   oSysPara:oMessage:anzeigen("Die Datenbank " + UPPER(::cDbank) + " hat eine kritische Grösse erreicht!!", + CRLF, +;
                                              "Am besten sofort eine Reduzierung der DatensΣtze veranlassen!!!",,,"W")
                ELSE                                                            // wenn dies nicht der Fall, dann braucht erst die Leerprüfung stattzufinden
                   IF ::lMin1Record .AND. ::cAlias <> "neu"                     // wird nur geprüft, wenn es keine Neuerstellung einer Db ist, weil die dann immer leer ist
                      IF (::nArea)->(LastRec()) = 0
                         (::nArea)->(DbAppend())
                         IF ::lMin1RecordHinweis
                            oSysPara:oMessage:anzeigen("Die Datenbank " + UPPER(::cDbank) + " hat noch KEINEN Datensatz. Bitte erfassen!")
                         ENDIF
                      ENDIF
                   ENDIF
                ENDIF
          RECOVER USING oError                                                  // und was macht dass hier?
                altd()         // der dient der Fehlersuche
                IF ++nVersuche > 5
                   IF oSysPara:oPruefen:fehlerbehandlung(oError,self)
                      LOOP
                   ENDIF
                ENDIF
          END SEQUENCE
          ErrorBlock(bSaveError)                                                // Standard wieder herstellen
          EXIT
       ENDDO .T.
RETURN self
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Antworten