Beiträge von LN4ever

    Ich verwende den gleichen Code sowohl in Agenten, die im Userkontext laufen als auch in Hinterggrund- oder zeitgesteuerten Agenten.


    Mit dem Versuch, einen Workspace zu öffnen, erhalte ich einen Fehler im (NichtUI)Agenten - und lasse bestimmte Ausgaben (Print, Abfragen, Messageboxes, Fortschrittsbalken) weg. Darum geht es.


    Wie willst du sonst (im identischen Code) herausfinden, ob es ein User-Interface gibt ?


    Wenn ich heute noch einmal anfangen müßte, all das zu programmieren, würde ich mir Klassen schreiben, die je nach Aufruf diese Variable per se setzen - und dann im Agentencode darauf reagieren.


    Aber es war ja auch nur eine Anmerkung zur Anmerkung.


    Gruß


    Norbert

    Zu der ANmerkung von Diali, daß man in Bibs bei zeitgesteuerten Agenten keine UI-Befehle nutzen darf, eine Anmerkung zur ANmerkung.


    Das stimmt, wenn man die Elemente als UI-Elemente deklariert. Werden sie als Variant deklariert, kann man sie einbauen, muß aber über ein ErrorHandling verhindern, daß sie als UI-Elemente angesprochen/verwendet werden.


    Z.B. habe ich eine kleine Routine laufen, die mir sagt, ob es ein UI gibt. Ich versuche, einen als Variant deklarierten Workspace als UIWorkspace anzusprechen - und fange die Fehlermeldung im Background-Fall ab. Damit weiß ich dann, daß ich kein UI habe.

    Große Systemhäuser haben teilweise erkannt, mit welch üblen Restriktionen "Gestaltung verbergen" verbunden ist und liefern ihre Werke ohne die verborgene Gestaltung aus.


    Nicht ganz - klar. Der Saft in der Tomate steckt in den Script-Libraries - und die sind durch Weglöschen der Textteile in den ausgelieferten Schablonen geschützt.


    Alles Andere macht überhaupt keinen Sinn. Das "Gestaltung verbergen" kann man ja in wenigen Minuten ohnehin "knacken", indem man sich in eine nicht geschützte Datenbank die Design-Objekte aus einer geschützten Datenbank hineinkopiert.


    Für die Versionen bis 4 geisterte die Weisheit herum, daß man im HEX-Editor das 122. Byte drehen müßte (ich lege meine Hand nicht für die Zahl 122 ins Feuer), in Version 4 war es dann etwas besser gemacht, aber mit der Klasse von Damien Katz für die Designelemente war das alles auch wieder für die Katz'.


    Wissen, Kraft und Mächtigkeit einer Notes-Anwendung stecken an so vielen Stellen, daß das Kopieren nur sehr vereinzelt Sinn machen kann.

    Wir warnen immer mit beständiger Inbrunst davor, Standardschablonen zu ändern - die "zusätzliche Spalte" in vielen Ansichten, vielleicht noch nachgezogen in mehrere Ordner, konterkariert diese Empfehlung.


    Du manipulierst mit deiner Methode Mails. Vielleicht lassen deine Benutzer das mit sich machen. Ich würde das nicht ungestraft durchgehen lassen.


    Was an einem Ausdruck "Igittigitt" ist, bleibt dein einsames Geheimnis. Habe ich gesagt, daß ich dafür Papier verwende ?
    PDF ist auch "Drucken".


    Ich verstehe mich an vielen Stellen längst wieder als "ganz normalen Benutzer" mit einigen herausgehobenen Entwickler- oder Administrations-Rechten. Was du propagierst, kann man durchaus als "mißbräuchliche Nutzung administrativer Rechte" bewerten. Welche Glaubwürdikeit haben auf dich die Menschen, über die man zu Recht sagt: Sie predigen Wasser und trinken Wein ?


    In welchem Maße bist du bereit, im Notesumfeld des täglichen Umgangs selbst auch das Wasser zu trinken, das du predigst ?

    Zitat

    Da komme ich nicht mit klar, ich bin wie gesagt nicht so bewandert mit der Programmierung.


    Dann mußt du es eben lassen. Oder manuell machen.
    Und wenn es doch wichtig ist, mußt du es lernen oder dir Beratung einkaufen.


    Das sind die vier möglichen Wege, die realistisch und erfolgversprechend sind (erfolgversprechend in dem Sinne, daß das erwartbare Ergebnis eintritt).


    Du kannst natürlich auch eine Mail mit 87 Screenshots versenden und die Anwender auffordern es selbst zu tun. Oder du kannst auf ein Wunder hoffen, oder einen Zufall. Aber diese Wege sind nicht erfolgversprechend im Sinne der obigen Definition.


    Und jetzt entscheide dich.

    Und warum muß es Script sein ?
    Mach dir doch einen Button in die Icon-Leiste mit
    @If(ReturnReceipt="1";@Prompt([OK];"Empfangsbestätigung";"");NULL)


    Dann drückst du kurz bei den Mails, bei denen du es wirklich vorher wissen willst drauf - und druckst sie aus, bevor du sie öffnest.

    Der Haken bei den Userpreferences, daß alle Mails standardmäßig signiert werden, sorgt vermutlich dafür - und führt bei Kalendereinträgen, die verändert werden, zu diesem Verhalten. In der Empfängermailbox muß ein Agent ja die "Absage" vermerken - und damit verändert er den Hash-Wert des Dokuments - und damit stimmt die Signatur nicht mehr. Alles logisch, aber für die Anwender verwirrend. Ich habe den Haken bei mir deshalb schon vor langer Zeit rausgenommen.

    Und für den Workspace gibt es ein todchices Retro-Design. Bei den Userpreferences der dritte Eintrag "TEXTURED WORKSPACE". Haken rausnehmen und du weißt, wie die Versionen 1 bis 3 aussahen.


    Der Vorteil: die Kacheln werden kleiner oder größer, wenn du den Servernamen anzeigen oder ausblenden läßt. Und wenn du beim Drücken von VIEW SERVERNAMES die CTRL- und SHIFT-Taste gedrückt hältst, dann siehst du auch den physischen Dateinamen. Und der steht in der Kachel und nicht auf dem schattierten Rand.


    Ich weiß zwar nicht, was die Kollegin damit anfangen kann, aber du kannst bestimmt damit schwer Eindruck schinden. You are the super-freak. Und war das nichht die eigentliche Frage ?

    Was heißt denn


    Zitat

    ... und ändere es bei Bedarf einfach ab,
    z.B. nur auf den Namen, bzw. hierachischen Namen


    Lesernamen funktionieren nur mit kanonischen Namen - das konntest du ja schon feststellen. Und jetzt kommt so ein Murks in deiner abschließenden Zusammenfassung. Das halte ich dann doch für eine Form von Beratungsresistenz, die eine besondere Beachtung verdient.


    Und jetzt zum Praktischen: bitte füge die Leserrollen nur dann ein, wenn es in einem Leserfeld bereits mindestens einen Namen gibt. Sonst kann nämlich jedes Dokument nur noch von den Inhabern dieser Rolle gelesen werden. Für die nicht rollengekrönten Häupter ist das Dokument verschwunden. Willst du das ?


    Und jetzt betrachten wir uns noch einmal dein Script, das in 6 Zeilen schon einige Ungereimtheiten aus den Weissagungen des Konfusius enthält:


    Dim item As NotesItem
    Dim lesen As String
    Set item = New NotesItem( docHistorie, "Reader", "[ReadAll]", READERS )
    item.IsReaders= True
    Call item.AppendToTextList( docHistorie.lesen )
    Call docHistorie.Save (True, True)


    Zeile 1 und Zeile 6 gehen in Ordnung.
    Für Zeile 2 sehe ich nirgends eine sinnvolle Bedeutung.
    Zeile 3 zeigt, daß du die Hilfe gelesen hast - sehr gut (!!!)
    Zeile 4 zeigt aber leider, daß du sie nicht ganz verstanden hast (und Zeile 3 in ihrer Art, wie du sie eingefügt hast, auch). Durch den Parameter READERS in Zeile 3 ist Zeile 4 nämlich überflüssig.
    Zeile 5 ist der eigentliche Hammer. An deinen neuen item willst du den Inhalt eines bestehenden Items dranhängen, aber du hängst ein item dran. Das kann nicht funktionieren.
    Und da wird klar, daß du nicht weißt, was "durchiterieren" ist. Steht auch in keinem Duden, ist ein häßliches Wort. iter ist lateinisch und heißt sowohl "Weg" als auch "Schritt" (das übliche denglische Wort "durchsteppen" ist ja schon für den Debugger besetzt). Wenn ich "iter" höre, denke ich immer noch an unseren Lateinlehrer, der uns mit dem schönen Spruch traktierte:
    "Os, os, iter, cor, ver, aes
    sind alle Neutrum wie vas, das Gefäß"
    (Zusatz - und ich immer bei mir dachte "wie Arsch, das Gesäß").


    Genug der Abschweifungen. Der Weg ist das Ziel, der Schritt ist das Mittel. Also - frisch ans Werk.


    ForAll xeintrag in docHistorie.Lesen
    If xEintrag<>"" Then
    Call item.AppendToTextList(xEintrag)
    End If
    End ForAll
    Das heißt "durchiterieren".


    Aber du solltest Zeile 5 (bzw. das Durchiterieren) am besten ganz sein lassen, denn du hast doch jetzt ein zweites Leserfeld READER, in dem dein Wert drinsteht. Leserfelder wirken additiv.


    Und zu Zeile 3 gibt es doch noch eine klitzekleine Anmerkung, die nicht ganz ohne Bedeutung ist. Wenn du das erste Mal mit deinem Script über ein Dokument läufst, bekommst du ein Feld READER, wunderbar. Wenn du das zweite Mal drüberläufst, bekommst du ein weiteres Feld READER. Und beim 26. Mal merkst du, daß du 26 gleichnamige Felder hast.


    Du wirst nicht der Erste sein, der sich eines Tages darüber ärgert, daß es zum Zugriff auf ein Feld nur ein "GetFirstitem" gibt. Leider fehlt bis jetzt im Vorrat von LS ein GetTwentysixthitem.


    Und wenn du dann eines Tages das Feld löschen sollst, dann mußt du 26 Mal mit deinem Agenten drüberlaufen, der das Feld löscht. Das Schlimme ist nicht daß du 26 Mal drüberlaufen mußt, sondern daß du gar nicht wissen wirst, wie oft du drüberlaufen mußt.


    Dein kleiner Agent hat mit 6 Zeilen Code (von denen 2 Zeilen selbstverständlich und 2 Zeilen "toter Code" sind) einen ganz erheblichen Schaden angerichtet. Über Zeile 6 haben wir an dieser Stelle noch gar nicht diskutiert. Dort ist die Richtigkeit der Parameter mit 2 dicken Fragezeichen zu versehen.Willst du wirklich einen Replikationskonflikt erzeugen, wenn jemand anders in dem Dokument eine Änderung vornimmt ?


    Aber wie wäre es richtig ?


    Damit ergibt sich doch ein schönes kleines Programm a la:


    Dim item As NotesItem
    Dim LeserVorhanden As Integer
    Dim DocHasChanged As Integer
    Dim i As Integer
    Dim Feldwerte As Variant


    DocHasChanged=False
    Feldwerte=docHistorie.GetItemValue("Lesen")
    LeserVorhanden=False
    For i=0 To UBound(Feldwerte)
    If Trim(Feldwerte(i))<>"" Then
    LeserVorhanden=True
    Exit For
    End If
    Next
    If LeserVorhanden Then
    If docHistorie.HasItem("Reader") Then
    Set item=docHistorie.GetFirstitem("Reader")
    If Not item.Contains("[ReadAll]") Then
    Call item.AppendToTextList("[ReadAll]")
    DocHasChanged=True
    End If
    Else
    Set item = New NotesItem( docHistorie, "Reader", "[ReadAll]", READERS )
    ElseIf docHistorie.HasItem("Reader") Then
    Call docHistorie.Removeitem("Reader")
    DocHasChanged=True
    End If


    If DocHasChanged Then
    Call docHistorie.Save (False, False)
    End If


    Du fügst das Feld nur dann ein - und speicherst auch nur dann - wenn es bereits Leser gibt und in dem Feld READER noch nicht deine Leserrolle drinstehht. Wenn es keine benamten Leser mehr gibt, löschst du es. Gibt es das Feld und deine Rolle steht noch nicht drin, hängst du deine Rolle an das Feld dran.


    Vielleicht ahnst du jetzt, warum es Berater gibt, die sich auf Notes spezialisiert haben, und warum es sinnvoll sein kann, denen einen Auftrag zu geben. 6 Zeilen Code stoppelt sich Jeder zusammen. 6 Zeilen sinnvollen Code - da wird die Luft schon dünner. Und 6 Zeilen sinnvollen und richtigen Code - da mußt du fast schon suchen.


    Warum schreibe ich das in dieser Ausführlichkeit ?


    Weil ich in letzter Zeit zunehmend den Eindruck gewinne, daß immer öfter Firmen von irgendwelchen Frischlingen, Praktikanten, Diplomanden und fragwürdigen Billiganbietern erwarten, daß die "auf die Schnelle" einmal eine Applikation auf die Beine stellen. Das böse Erwachen kommt erst viel später, denn der äußerliche Chic einer Anwendung läßt keinerlei Rückschlüsse auf die "inneren Werte" zu. Und das Meiste, was ich bis jetzt gesehen habe, ließ diese inneren Werte vermissen.


    Ich weiß: ich habe dich arg gescholten. Das geht überhaupt nicht gegen dich persönlich. Du hast nur ein so typisches - und vor allem kurzes - Stück Codeschnipsel in die Runde geworfen, an dem sich einmal eemplarisch zeigen ließ, daß in jeder Zeile, in jedem Parameter etwas steckt, was wichtig ist.


    Ich hoffe, daß ich dir im Gegenzug auch ein wenig geholfen habe.

    Eine "generelle Weiterleitung" ist - vor allem im Falle der Weiterleitung an eine Internet-Adresse - nicht ungefährlich, weil sie nur im Fall rückmeldefreier und fehlerfreier Kommunikation reibungslos funktioniert. Ob sie mit betrieblichen Vereinbarungen oder sonstigen Regeln (vielleicht auch Gesetzen) kollidiert, sei vorerst einmal dahingestellt.


    Ein Beispiel aus der Praxis: Ein Benutzer leitete sich alle Mails an seinen t-online Anschluß weiter. An einem Wochenende gab es einen Ausfall bei t-online. Dank besonderer Servicefreundlichkeit sendete t-online aber jedem, der einen Zustellversuch unternahm, eine Mitteilung, daß dies im Moment nicht möglich sei ...
    Natürlich wurde diese Nachricht wieder an t-online weitergeleitet - und es ergab sich ein Test der Reaktionsgeschwindigkeit von zwei miteinander kommunizierenden Servern. Am Montagmorgen verstopften 70.000 Mails den zentralen Router eines international operierenden Unternehmens. Natürlich waren unter den 70.000 Mails neben den Verstopfern inzwischen auch viele Mails aufgelaufen, die man nicht einfach mit "ALLE MARKIEREN" löschen konnte.


    Eine solche Aktion kann also ein ganzes Unternehmen für eine geraume Weile von seinen Kommunikationsmöglichkeiten abhängen.


    Bevor du jetzt weiter an deiner Regel feilst, überleg dir, mit welcher guten Entschuldigung du in einem solchen Falle aufwarten kannst, die ein solches Risiko rechtfertigt.


    Und wenn du eine hast, dann feile mal schön weiter an deiner Regel.

    Es reicht doch, den Volltextindex von der betroffenen Datenbank zu löschen. Alles Andere ist auch ganz nett, aber wenn der NSD im UPDATE-Task abstürzt, dann gibt es doch zunächst einmal nur ein Problem mit einem Volltextindex.


    Und FIXUP und COMPACT grteifen den FT überhaupt nicht an, lösen also auch nicht das Problem.

    Es gibt für den Königsweg ein Kaiser-Statement in den Options, und das lautet


    Options Declare


    Dann wird dir jede Variable, die du nicht deklariert hast (Tippfehler, Namensverwechslung) um die Ohren gepfeffert, noch bevor du das erste Mal abspeicherst.


    Das kostet ein paar Minuten - und spart Stunden.


    Könnte man doch glatt als "effektiv" bezeichnen.


    Wenn du das bei größeren Scripts im Nachhinein einfügst, stehen dir manchmal die Haare zu Berge, wie dein Script überhaupt halbwegs fehlerfrei durchlaufen konnte, weil du IF-Zweige auf falsch geschriebene, leere, nicht gefüllte Variablen durchlaufen hast.


    Könnte man also glatt als "sehr effektiv" bezeichnen.

    Also bevor ich das $READERS-Feld zum Einsatz bringe, würde ich mir eher einen privaten Schlüssel generieren, in meine ID einbinden und damit verschlüsseln. Dann sehen die Leser zwar den Termin und das Subject, nicht aber die weiteren Einträge zum Termin. Muß man halt wissen und beachten.

    Und wie wäre es für den Anfang mit einer kleinen Aktion im Dokument


    UNID := @Text(@DocumentUniqueID);
    @Command([GoUpLevel]);
    @Command([OpenDocument];"0";UNID);
    @Command([FileCloseWindow])


    Wenn du in der Ansicht stehst (und das ist nicht die gewünschte Ansicht), kannst du bei gedrückter STRG-Taste dann in eine andere Ansicht wechseln und stehst wieder auf dem Dokument, wenn es in der anderen Ansicht angezeigt wird.


    Du kannst hinter das GoUpLevel ja noch ein @Command([OpenView]) setzen, wenn du zu einer ganz bestimmten Ansicht willst. Testen !

    Ich würde raten, die Diskussion mit dem Anwender noch einmal zu führen, um zu prüfen, ob da nicht ein großes Mißverständnis vorliegt. Ich kenne NIEMAND, der beide Sprachen gleichzeitig sehen will. Die wollen doch nicht mit deiner Datenbank einen Online-Englisch-Nachhilfekurs haben.


    Und wenn es kein Mißverständnis ist, dann kannst du immer noch anbieten, die Outline zu verdoppeln und einen DEUTSCH- und einen ENGLISCH-Zweig zu machen, in dem dann jeder Eintrag einzeilig ist.

    Ich würde DRINGENDST davon abraten, in DLLs herumzumanipulieren, und zwar unabhängig davon, ob es geht und ob es vielleicht bei deinem Testclient zu einem brauchbaren Ergebnis führt.


    Wenn bei Tausenden von Benutzern an einem schönen Morgen der Virenscanner der nächsten Generation entdeckt, daß die Hash-Werte der verwendeten DLL-Datei nicht mit der Vorgabe übereinstimmt, wird er die DLL in Quarantäne nehmen. Dann läßt sich in einem Konzern plötzlich kein Notes-Client mehr starten.


    Super !


    Und als Entschuldigung murmelt jemand, ihm habe der Hintergrund der Kachelwand nicht gefallen.


    Oder: in einem schwerwiegenden Wartungsfall wird IBM verständlicherweise jeden Support ablehnen. Und ihr fangt an, die Original-DLL wieder zu verteilen.


    Notes ist doch keine Spielwiese, auf der sich die Jünger der "Schöner Wohnen"-Gefälligkeitsgrafiken tummeln müssen.

    Mit REPLACEITEMVALUE


    Syntax
    Set notesItem = notesDocument.ReplaceItemValue( itemName$, value )
    Parameters
    itemName$
    String. The name of the item(s) you want to replace.
    value
    The value of the new item. The data type of the item depends upon the data type of the value, and does not need to match the data type of the old item.
    Hinweis ReplaceItemValue method takes the NotesDateTime object as input directly.

    Am Einfachsten erstellst du in einer für Alle zugänglichen Mail-In-Datenbank eine Vorlage mit dem Namen FAX - und jeder kopiert diese in seine Mailbox und modifiziert sie.


    Nach dem Eintragen der persönlichen Daten muß jeder Benutzer die modifizierte Vorlage mit neuem Namen als Vorlage speichern - und kann sie ab da benutzen. Anschließend schmeißt er die alte FAX-Vorlage weg.


    Mail-In-DB und darin Vorlage (anstelle einer gewöhnlichen Mail), damit nicht die ganzen Sendeinformationen fälschlicherweise bereits in den Vorlagen stehen.