Das Notes Forum

Domino 9 und frühere Versionen => ND7: Entwicklung => Thema gestartet von: bikerboy am 17.03.09 - 15:24:16

Titel: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 17.03.09 - 15:24:16
Hallo ,

ich habe hier gerade ein mittleres Problem.

Ich soll per Skript eine Schablone, einer DB erstellen und den Skriptcode aus den Libaries in eine Lss exportieren und wieder per %Include einbinden.

Geschafft habe ich schon folgendes.

- Zugriff auf die Designelemente per NotesNoteCollection
- Erstellen sauberer lss-Dateien ( Die scheinen sauber zu sein, weil sie über den Frontend Import im Designer funktionieren)


Mein Problem besteht nun darin, dass die Bibliotheken nach meiner Anpassung nicht mehr funktionieren und als Fehlermeldung "General LSE Failure"

Habt ihr ne Idee was es sein könnte.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Axel am 17.03.09 - 15:49:01
Was hast du genau angepasst? Wann kommt die Fehlermeldung?

Zeigt %Include auch dahin, wo die lss-Dateien zu finden sind? Ich denke da z.B. an Schreibfehler beim Dateinamen.

Axel


Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 17.03.09 - 16:03:40
Also inhalt des $ScribLib steht folgendes

"'++LotusScript Development Environment:2:5:(Options):0:74
%INCLUDE "lslDeleteGroupRequest.lss"

'++LotusScript Development Environment:2:5:(Forward):0:1'

'++LotusScript Development Environment:2:5:(Declarations):0:2'"


und die lss liegt im Programmvz von notes.

Bei Öffnung der ScribLib ist unter Options nichts zu sehen.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Axel am 17.03.09 - 18:03:51
Sorry, aber diese Angaben verwirren mehr als sie helfen.

Bei Öffnung der ScribLib ist unter Options nichts zu sehen.

Welche ScribLib ist hier gemeint?

Also inhalt des $ScribLib steht folgendes

"'++LotusScript Development Environment:2:5:(Options):0:74
%INCLUDE "lslDeleteGroupRequest.lss"

'++LotusScript Development Environment:2:5:(Forward):0:1'

'++LotusScript Development Environment:2:5:(Declarations):0:2'"

Betrifft das die ScriptBibliothek in der Datenbank?

Im Ausgangsposting schreibst du was von Libraries. Ich sehe hier aber nur eine. Was ist mit den anderen?

Je mehr und detailiertere Informationen du lieferst, um so besser kann dir geholfen werden.

Mach das Ganze nochmal rückgängig und schau ob's dann wieder funktioniert. Dann Schritt für Schritt nochmal den Code exportieren, die Bibliothek leeren und unter dem Options - Abschnitt die lss-Datei mit %Include einfügen. Da ist irgendwas schiefgegangen (fehlender Verweis, Schreibfehler etc).

Axel
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 23.03.09 - 08:23:59
So nach langer Abwesenheit (bedingt dur Krankheit), nun die Auflösung

Ich will den Code aus vielen Bibliotheken per Skript in lss-Dateien auslagern. Das klappt auch schon. Wenn ich nun aber das Feld "$ScribLib" mit dem Oben geposteten Code fülle und nach der Verarbeitung die Bibliothek aufmache, bekomme ich die oben genannte Fehlermeldung.

Mein Problem ist nun, dass die Bibliotheken im optischen Vergleich gut aussehen.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 23.03.09 - 08:58:15
 
Code
 
	arrReplace(0) = {'++LotusScript Development Environment:2:5:(Options):0:74}+ Chr(9) 
	arrReplace(1) = {%INCLUDE "} + strFilePath + {"}+ Chr(9) 
	arrReplace(2) = {'++LotusScript Development Environment:2:5:(Forward):0:1'} + Chr(9) 
	arrReplace(3) = {'++LotusScript Development Environment:2:5:(Declarations):0:2'}+ Chr(9) 
	
	Call doc.ReplaceItemValue(FIELDVAL,Implode(arrReplace,Chr(13)))
	Call doc.Save(True,False, True)

Das ist der Momentane Code, den ich im Design-Dokument hinterlege
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: koehlerbv am 25.03.09 - 21:47:10
Das Exportieren mag ja nicht das Problem sein, aber mir erschliesst sich nicht, wofür das gut sein soll: Warum das Rad nochmals erfinden, das tut doch der Teamstudio Analyzer sowieso besser.

Das Wieder-Einbinden führt so logischerweise zu Fehlern, weil das Importieren selbst ja nicht das Problem darstellt - der Code muss dann ja auch kompiliert werden  ;D
Aber auch für diesen Import geht mir der sinnvolle Einsatzzweck ab.

Bernhard
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 26.03.09 - 10:49:25
Bis jetzt haben wir Schablonen für Kunden, die den Code nicht sehen soll, per Hand erstellt, nun haben wir aber eine mittelgrosse Anwendung mit an die 50 Bibliotheken bei denen es halt ewig dauert bis man eine fertige Schablone erstellt hat. Das soll halt über die mein Tool nun abgeschaltet werden.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 31.03.09 - 13:27:36
...
- Erstellen sauberer lss-Dateien ( Die scheinen sauber zu sein, weil sie über den Frontend Import im Designer funktionieren)
....


So bei manchen Exporten hat er doch seine Probleme. Kennt jemand nen Weg wie ich per skript die Bibliotheken in ne LSS exportieren kann.

Besten Dank schon mal
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Johnson am 31.03.09 - 15:40:46
Per API-Funktion NSFItemInfo.

Ok... Das ist jetzt zwar ein riesiger Code und er bezieht sich auf Agenten, ABER:
Script Libraries und Agents sind vom Class-Typ "Filter". Sie werden lediglich von ihren Flags ($Flag-Feld) differenziert.

Ich habe es jetzt nicht ausprobiert, ob es mit Script Libraries wirklich funktioniert, aber theoretisch?...

Den Code hier must du also noch umschreiben und anpassen, denn er stammt aus einer Agentendatenbank von mir.

Code
Const ODS_DWORD = 0

Type BlockID
   pool As Long
   block As Long
End Type

Type WSIG
   signature As Integer
   length As Integer
End Type

Type CDACTIONLOTUSSCRIPT
   header As WSIG
   dwFlags As Long
   dwScriptLen As Long
End Type

Type CDACTIONFORMULA
   header As WSIG
   dwFlags As Long
   dwFormulaLen As Long
End Type

Declare Sub apiOSMemFree Lib "nnotes.dll" Alias "OSMemFree" (Byval handle As Long)
Declare Function apiNSFFormulaDecompile Lib "nnotes.dll" Alias "NSFFormulaDecompile" (Byval P As Long, Byval S As Integer, hT As Long, N As Long) As Integer
Declare Function apiNSFItemInfo Lib "nnotes.dll" Alias "NSFItemInfo" (Byval lng_notehandle As Long, Byval str_itemname As Lmbcs String, Byval int_namelen As Integer, bi_item As BlockID, int_valuedatatype As Integer, bi_value As BlockID, lng_valuelen As Long) As Integer
Declare Function apiOSLockObject Lib "nnotes.dll" Alias "OSLockObject" (Byval handle As Long) As Long
Declare Sub apiOSUnlockObject Lib "nnotes.dll" Alias "OSUnlockObject" (Byval handle As Long)
Declare Private Sub apiPeek Lib "MSVCRT" Alias "memcpy" (D As Any, Byval P As Long, Byval N As Long)
Declare Sub apiODSReadMemory Lib "nnotes.dll" Alias "ODSReadMemory" (pSource As Long, Byval typeODS As Integer, pDest As Any, Byval Iterations As Integer )
Declare Sub apiPeekString Lib "MSVCRT" Alias "memcpy" (Byval D As String, Byval P As Long, Byval N As Long)

Sub Click(Source As Button)
   
   Dim ag As NotesAgent
   Dim bi_item As BlockID
   Dim bi_value As BlockID
   Dim db As NotesDatabase
   Dim db_check As NotesDatabase
   Dim dc As NotesDocumentCollection
   Dim doc As NotesDocument
   Dim doc_ag As NotesDocument
   Dim int_apiresult As Integer
   Dim int_valuedatatype As Integer
   Dim lng_dbhandle As Long
   Dim lng_notehandle As Long
   Dim lng_valuelen As Long
   Dim lng_buffer As Long
   Dim rec As CDACTIONLOTUSSCRIPT
   Dim s As NotesSession
   Dim str_agent As String
   Dim str_item As String
   Dim str_unid As String
   Dim uidoc As NotesUIDocument
   Dim uiws As NotesUIWorkspace
   
   
' ### initialize ###
   
   Set uiws = New NotesUIWorkspace
   Set uidoc = uiws.CurrentDocument
   Set doc = uidoc.Document
   Set s = New NotesSession
   Set db = s.CurrentDatabase
   
   
' ### validation ###
   
   If doc.LogServer(0) = "" Or doc.LogDatabase(0) = "" Or doc.LogObject(0) = "" Then
      Messagebox "Missing informations", MB_OK + MB_ICONEXCLAMATION, db.Title
      Exit Sub
   End If
   
   
' ### open source database ###
   
   Set db_check = s.GetDatabase(doc.LogServer(0), doc.LogDatabase(0), False)
   If db_check Is Nothing Then
      Messagebox "File " & doc.LogDatabase(0) & " does not exist", MB_OK + MB_ICONEXCLAMATION, db.Title
      Exit Sub
   End If
   
   
' ### get agent name ###
   
   str_agent = doc.LogObject(0)
   If Instr(str_agent, "|") > 0 Then str_agent = Strleft(str_agent, "|")
   
   
' ### get agent ###
   
   Set ag = db_check.GetAgent(str_agent)
   If ag Is Nothing Then
      Messagebox "Could not find agent " & str_agent & " in database " & doc.LogDatabase(0), MB_OK + MB_ICONEXCLAMATION, db.Title
      Exit Sub
   End If
   
   
' ### get universal id of the agent ###
   
   str_unid = Strleft(Strright(ag.NotesURL, ".nsf/"), "?OpenAgent")
   If str_unid = "" Then
      Messagebox "Could get UniversalID of the agent " & str_agent & " in database " & doc.LogDatabase(0), MB_OK + MB_ICONEXCLAMATION, db.Title
      Exit Sub
   End If
   
   
' ### get design document ###
   
   Set doc_ag = db_check.GetDocumentByUNID(str_unid)
   If doc_ag Is Nothing Then
      Messagebox "Could not get design document of the agent " & str_agent & " in database " & doc.LogDatabase(0), MB_OK + MB_ICONEXCLAMATION, db.Title
      Exit Sub
   End If
   
   If Instr(doc_ag.~$Flags(0), "L") = 0 Then
      Messagebox str_agent & " is not an lotus script agent!", MB_OK + MB_ICONEXCLAMATION, db.Title
      Exit Sub
   End If
   
   
' ### get item informations ###
   
   str_item = "$AssistAction"
   int_apiresult = apiNSFItemInfo(doc_ag.handle, str_item, Len(str_item), bi_item, int_valuedatatype, bi_value, lng_valuelen)
   If Not(int_apiresult = 0) Then
      Error int_apiresult, BEGetAPIError(int_apiresult)
   End If
   
' ### read informations ###
   
   lng_buffer = apiOSLockObject(bi_value.Pool) + bi_value.Block ' LockBlock(vB)
   
   Call apiODSReadMemory (lng_buffer, ODS_DWORD, rec.header.signature, 1)
   Call apiODSReadMemory (lng_buffer, ODS_DWORD, unknown, 1)
   Call apiODSReadMemory (lng_buffer, ODS_DWORD, rec.dwFlags, 1)
   Call apiODSReadMemory (lng_buffer, ODS_DWORD, rec.dwScriptLen, 1)
   
   Dim word As Long
   Dim code As String
   Dim i As Integer
   code = ""
   
   For i = 7 To rec.dwScriptLen -5
      apiPeek word&, lng_buffer + i, 1
      If word& > 0 Then code = code & Chr$(word&)
   Next
   
   Call apiOSUnlockObject(bi_value.Pool)
   
   
   
' ### open source code ###
   
   Dim doc_dlg As NotesDocument
   Dim item As NotesItem
   Dim rti As NotesRichTextItem
   Set doc_dlg = db.CreateDocument
   doc_dlg.Form = "AgentSourceCode"
   doc_dlg.Agent = ag.Name
   Set item = New NotesItem(doc_dlg, "Server", db_check.Server, NAMES)
   Set rti = doc_dlg.CreateRichTextItem("Link")
   Call rti.AppendDocLink(db_check, db_check.Title)
   Call rti.Update
   
   doc_dlg.Code = code
   
   Call uiws.EditDocument(False, doc_dlg, True)
   
End Sub

Gruß
Johnson
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Johnson am 31.03.09 - 15:44:08
Das interessiert mich jetzt selber. Ich probiere das heute mal aus.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Johnson am 31.03.09 - 16:23:39
Und eh ich es vergesse. Kompilieren geht mit der Funktion NSFNoteLSCompile bzw. NSFNoteLSCompileExt.
Aber eine Library einzeln zu kompilieren kann auch noch andere "nette" Nebeneffekte haben. Wie z.B. "type mismatch on external name"....

Dann ist es besser die gesamte Datenbank zu komilieren.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Johnson am 31.03.09 - 20:41:38
Also. Ich wollte erst noch was anderes versuchen. Und siehe da:  :o Mit einem DXL-Export bekommt man eine sauberes lss-File.

Code
Sub Initialize
    
    Dim db As NotesDatabase
    Dim doc_lss As NotesDocument
    Dim nddn As NotesDOMDocumentNode
    Dim nde As NotesDXLExporter
    Dim ndp As NotesDOMParser
    Dim nnc As NotesNoteCollection
    Dim ns As NotesStream
    Dim s As NotesSession
    Dim str_dxl As String
    Dim str_noteid As String
    Dim var_lotusscript As Variant
    
    Const LSS_FILEPATH = "C:\lib.lss"
    Const LIB_NAME = "lss"
    
    
' ### initialize ###
    
    Set s = New NotesSession
    Set db = s.CurrentDatabase
    
    
' ### build note collection ###
    
    Set nnc = db.CreateNoteCollection(False)
    nnc.SelectScriptLibraries = True
    Call nnc.BuildCollection
    
    
' ### get lss library ###
    
    str_noteid = nnc.GetFirstNoteId
    Do Until str_noteid = ""
        
        Set doc_lss = db.GetDocumentByID(str_noteid)
        If Not(doc_lss Is Nothing) Then
            If doc_lss.~$Title(0) = LIB_NAME Then Exit Do
        End If
        
        str_noteid = nnc.GetNextNoteId(str_noteid)
    Loop
    If doc_lss Is Nothing Then Goto terminate
    
    
' ### get lotus script code ###
    
' create dxl exporter
    Set nde = s.CreateDXLExporter
    nde.ValidationStyle = VALIDATIONSTYLE_NONE
    nde.OutputDOCTYPE = True
    nde.DoctypeSYSTEM = ""
    
' export to string
    str_dxl = nde.Export(doc_lss)
    
' create a new dom parser object
    Set ndp = s.CreateDOMParser(str_dxl)
    Call ndp.Parse
    
' get the noted dom document note
    Set nddn = ndp.Document
    
' get lotus script code
    var_lotusscript = GetLotusScriptCode(nddn)
    
    
' ### create lss file ###
    
    Set ns = s.CreateStream
    If ns.Open(LSS_FILEPATH) = False Then Goto terminate
    
    Forall str_line In var_lotusscript
        Call ns.WriteText(Cstr(str_line))
    End Forall
    
    Call ns.Close
    
    
' ### terminate ###
    
terminate:
    Set db = Nothing
    Set doc_lss = Nothing
    Set nddn = Nothing
    Set nde = Nothing
    Set ndp = Nothing
    Set nnc = Nothing
    Set ns = Nothing
    Set s = Nothing
    
End Sub

Function GetLotusScriptCode(nddn As NotesDOMDocumentNode) As Variant
    
    Dim astr_code() As String
    Dim lng_code As Long
    Dim ndnl As NotesDOMNodeList
    Dim ndelement As NotesDOMElementNode
    Dim ndn_code As NotesDOMNode
    
    
' ### search lotusscript tags ###
    
    Set ndnl = nddn.GetElementsByTagName("lotusscript")
    If ndnl.NumberOfEntries = 0 Then Goto terminate
    
    Redim astr_code(ndnl.NumberOfEntries - 1)
    For lng_code = 1 To ndnl.NumberOfEntries
        Set ndelement = ndnl.GetItem(lng_code)
        If ndelement.HasChildNodes Then
            Set ndn_code = ndelement.FirstChild
            If Not(ndn_code.IsNull) Then
                astr_code(lng_code - 1) = ndn_code.NodeValue
            End If
        End If
    Next
    
    
' ### return value ###
    
    If lng_code > 1 Then GetLotusScriptCode = astr_code
    
    
' ### terminate ###
    
terminate:
    Set ndnl = Nothing
    Set ndelement = Nothing
    Set ndn_code = Nothing
    Exit Function
    
End Function

Aber dein größeres Problem ist der Import. Den kannst du auch über einen DXL Export/Import erledigen:
1. Designelement als DXL exportieren.
2. DXL bearbeiten.
3. DXL in das Designelement wieder importieren.
4. Kompilieren (Viel Spaß)

Dafür noch mal eine dumme Frage (denn ich glaube, dass ihr auch schon daran gedacht habt). Wenn es so wichtig ist, dass euer Kunde den Code nicht sehen kann, warum versteckt ihr nicht einfach das Design der Templates?

Denn dir ist schon klar, dass dabei der Code überall da "includet" wird, wo die Library (Libraries) aufgerufen wird (werden).
=> Das Design der Datenbank wird aufgebläht.

Ebenso kann das Designelement, dass das lss-File "includet", nicht geändert/gespiechert/kompiliert werden, wenn man das lss-File nicht im Programmverzeichnis von Notes hat.
=> Änderungen am Design sind dann unmöglich. Also warum nicht gleich das Design verstecken?
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: koehlerbv am 31.03.09 - 20:54:16
Statt "hide design" kann man auch einfach den Klartext des LotusScript-Routinen entfernen (Tool / eigenes Programm vorausgesetzt). Mit "hide design gibt es ja immer mal wieder Probleme und schliesst den Kunden zudem ganz von Änderungen aus ...

Bernhard
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Johnson am 31.03.09 - 20:56:26
Dumme Frage die 2.: Was meinst du mit "Klartext des LotusScript-Routinen entfernen" Bernhard?
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: koehlerbv am 31.03.09 - 22:05:12
In den Design-Elementen steht der Code im Klartext (für das Kompilieren) und in tokenisierter Form (nach dem Kompilieren). Nur letzterer ist dann noch erforderlich, ersterer kann für derartige Kundenversionen vollkommen problemlos entfernt werden. Dies ist auch ein vollkommen übliches Verfahren.

Bernhard
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 01.04.09 - 08:21:13
@Bernhard hat Recht

Wir müssen immer wieder mal Änderungen vornehmen, deswegen kann das Design nicht vollkommen versteckt werden.

Da nach einer Änderung auch mal recompiliert werden muss, includen wir den Code halt per LSS.

Werde den Code gleich mal ausprobieren.

Der Import läuft mittlerweile auch, mein Problem war, das eine lsl immer fehlerhaft war weil meine Funktion Probleme mit den grossen Bibliotheken hat.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 01.04.09 - 10:06:03
So habe deinen 2. Code mal ausprobiert und bin begeistert, hat nur bei einer bibliothek probleme

Wie sehen denn deine LSS - Dateien aus, ich habe am ende der Datei quasi nochmal den ganzen Code drunter, nachdem ich das abgestellt haben läuft es super, aber die LSS dateien sehen nicht mehr so schön aus
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: Johnson am 01.04.09 - 10:20:15
Ich habe das auch nochmal getestet.

Wenn du den Export nochmals laufen lässt, öffnet er ja eine existierende lss-Datei.
Also: Ändere
Code
If ns.Open(LSS_FILEPATH) = False Then Goto terminate
In
Code
If ns.Open(LSS_FILEPATH) = False Then Goto terminate
	Call ns.Truncate
Damit wird der bestehende Inhalt einer lss-Datei gelöscht.

Ebenso solltest du den Dateinamen der lss-Datei nicht durch die LSS_NAME Konstante angeben (das war nur der Einfachkeit halber), sondern dafür den Namen der Library verwenden.

Ansonsten sieht bei mir der Code ganz normal aus. Was meinst du denn mit "nicht mehr so schön"?

Ich glaube, dass es manchmal sein kann, dass in einem DXL die Zeilen nicht mehr untereinander kommen, sondern hintereinander in einer Zeile stehen. Das hatten wir mal bei ein paar Scripten.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: AndreasB am 01.04.09 - 17:01:52
hi,

wenn du folgenden code noch entsprechend abänderst, dann sehen die LSS-Files auch wieder "schön" aus! :-)

   Forall str_line In var_lotusscript
      var_newLine = Split(str_line, Chr(10))
      Forall element In var_newLine
         Call ns.WriteText(Cstr(element), EOL_CRLF)
      End Forall
   End Forall
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: bikerboy am 02.04.09 - 12:45:21
Ja cool dann ist das Ding schon fast fertig. Ich werde mal sehen, was ich hier veröffentlichen darf, auf jedenfall sollte ich nun jedem erstmal helfen können der Fragen dazu hat.

Werde noch eine Funktion einbauen, die die gesamte DB kompiliert und fertig ist das.
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: koehlerbv am 02.04.09 - 21:15:23
Ich verstehe immer noch nicht, warum Ihr für Kundenversionen einen dermassen G'schiss macht: LS-Klartext entfernen aus der Kundenversion und fertig. Das beeinflusst keine vorangegangene Kompilierung, keine Entwicklungsversion "voll krass mit allem", von dem die Kundenversion ja nur eine Kopie ist etc. pp.

Bernhard
Titel: Re: Code per Skript exportieren und einbinden
Beitrag von: ichnur am 11.11.09 - 09:05:50
Ok, ist zwar schon älter, aber ich kam über Google wegen einem "General LSE Failure" hierher.

Die in meinem Fall banale Lösung: Script Bibliothek neu speichern, dann gings wieder.
Vielleicht brauchts ja jemand anders.

Schönen Tag
Annette