• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Lotus Script: взгляд изнутри

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
VladSh
Прошу уточнить:
1. Это тесты со взятием значения из поля или просто строковые переменные?
2. Если поле числовое, но надо проверить заполнено ли оно. Такого Test-case не было?
 

VladSh

начинающий
Lotus Team
11.12.2009
1 784
157
BIT
57
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Тесты вычитки значений из списка и массива.</div></div><div class="sp-body"><div class="sp-content">Методика похожая, как описывал выше.

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код: вычитка с помощью For</div></div><div class="sp-body"><div class="sp-content">
Код:
length& = 1000

Dim lst List As String
For i& = 0 To length&
lst(i&) = Cstr(i&)
Next

startTime = Getthreadinfo(6)

For i& = 0 To length&
Print lst(i&)
Next

Print Format$((Getthreadinfo(6) - startTime) / Getthreadinfo(7), "##.00")
Код:
length& = 1000

Redim arr(length&) As String
For i& = 0 To length&
arr(i&) = Cstr(i&)
Next

startTime = Getthreadinfo(6)

For i& = 0 To length&
Print arr(i&)
Next

Print Format$((Getthreadinfo(6) - startTime) / Getthreadinfo(7), "##.00")
Числа возвращает странные, скорее всего это в минутах, а не в секундах, т.к. если умножить на 60, то получим приблизительно реальную картину.

Результаты при 1000:
Код:
List 0.20
Array 0.22

Array 0.22
List 0.22

Array 0.23
List 0.27

List 0.23
Array 0.28
Задумал сделать тесты на 5000, скорость упала при первых же итерациях, такое ощущение, что где-то в нотусне зашито падение производительности в зависимости от количества итераций.

Результаты при 5000:
Код:
List 2.32
Array 2.09
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код: вычитка с помощью Forall</div></div><div class="sp-body"><div class="sp-content">
Код:
length& = 5000

Dim lst List As String
For i& = 0 To length&
lst(i&) = Cstr(i&)
Next

startTime = Getthreadinfo(6)

i& = 0
Forall element In lst
Print lst(i&)
i& = i& + 1
End Forall

Print Format$((Getthreadinfo(6) - startTime) / Getthreadinfo(7), "##.00")
Код:
length& = 5000

Redim arr(length&) As String
For i& = 0 To length&
arr(i&) = Cstr(i&)
Next

startTime = Getthreadinfo(6)

i& = 0
Forall element In arr
Print arr(i&)
i& = i& + 1
End Forall

Print Format$((Getthreadinfo(6) - startTime) / Getthreadinfo(7), "##.00")
На удивление падение производительности при 5000 такое же, как и у цикла For, такое ощущение, что они от общего предка.

Результаты при 5000:
Код:
List 2.22
Array 2.23
Результаты при 1000:
Код:
List 0.22
Array 0.22
Пробовал тесты со строковым типом в тэгах списка, результат тот же.

Общий вывод: данные из массива по индексу и данные из списка по хэшу вычитываются примерно одинаково, расхождения укладываются в погрешность измерений.
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
данные из массива по индексу и данные из списка по хэшу вычитываются примерно одинаково
Поучается: массив и список наследники одного объекта в разных вариациях?
Но скорее всего они используют общий механизм доступа к значениям, которому плевать индекс там или хеш.
Думаю в общем виде это обычный сишний линейный список, даже дерево скорее.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
предполагаю что падение связано с буферами у Print (вернее у той части в кот. оно выводит) - надо убрать попробовать (в циклах)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"тест по зависимости от кол-ва"</div></div><div class="sp-body"><div class="sp-content">
Код:
Sub Initialize
Dim result As String, counts As String
counts = {10000, 20000,30000,40000,50000,60000,70000,80000,90000,100000}
Dim arr
arr=Split(counts,{,})
For c&=0 To Ubound(arr)
length&=Clng(arr(c&))
Dim lst List As String
For i& = 0 To length&
lst(i&) = Cstr(i&)
Next

Dim startTime As Long, endTime As Long
startTime = Getthreadinfo(6)

Dim s As String
For i& = 0 To length&
'		Print lst(i&)
'тупо копируем стринги
s={} &lst(i&)
Next
endTime=Getthreadinfo(6)
result=result &{cnt:} &arr(c&) & {;tics:} &Cstr(endTime- startTime) & Chr(10)
Next
Print result
Msgbox result
End Sub
из чего видим отсутствие скачкообразного изменения (в разы) от кол-ва, в отличии от принта - т.е. буфер у принта
 

VladSh

начинающий
Lotus Team
11.12.2009
1 784
157
BIT
57
Коллеги, а может кто-то запостит баг в их репозиторий, у кого есть доступ к нему?
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
чесногря я не считаю это багой, скорее - фича :D
ну кому надо принтовать стока раз... ?
а буфер завязан на вывод в лог/файл и окно...
 
P

phantom76

Вот, кстати коллеги про такой баг, кто-нибудь знает:

@Command([FileExport]; "Microsoft RTF";file); - не корректно работает при преобразовании таблиц на форме, особенно, когда есть вложенные.

команда хорошо отрабатывает на англоязычный эклипсовых клиентах версии 8.5.X и криво для клиентов 8.5.X basic и эклипсовых русских ( на других не тестировал)
В итоге пришлось от нее отказаться и генерировать файл скриптом, а жаль как быстрое решение не требующее установленного офиса очень не плохое.
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
Тут задачка была, в ходе нее выяснилось, что документы по разному открываются в разных библиотеках, ну и результат на экране оказался разный. Начал копать, ну и получилась такая версия, может прописные истины, но сам знал только о паре:
1. Если желтый линк в документе (copy-paste), то документ будет открываться на основании представления из которого его выбрали.
Если такого представления нет, то по дефолтному представлению.
2. Если желтый линк программно создавать, то там 2 пути. Опять же на основании выбранного представления, либо если через недокументированную функцию из представления, которое указано в ней.
3. NotesUIWorkSpace.URLOpen - открывает на основании представления, но UNID этого представления 0.
Если заменить этот 0 на UNID нужного, то будет открываться на основании представления по такому UNID.
Там еще и реплику можно поменять и сервер.
4. NotesUIWorkSpace.EditDocument - а вот это песня... Документ получается, скорее всего, методом аналогичным NotesDatabase.GetdocumentByUNID (ByNoteID), естественно через API.

Так вот, зачем я это здесь написал? Чтобы самому не забыть, ибо могу.
Столкнулся я с этим, когда в одной базе мы почти во всех вьюхах прописали FormFormula, чтобы документы открывались по другим формам.
И вот метод номер 4 нам подпортил все карты, так как в части документов нет желтых ссылок, а есть только Hot-Spot по нажатию на который открывается документ. Документы мы получали через UNID ну и вьюху ByUNID. Будем менять теперь.
Вот таки дела...
 

VladSh

начинающий
Lotus Team
11.12.2009
1 784
157
BIT
57
1-3 - всё вроде верно.
4 - в EditDocument передаётся объект NotesDocument (т.е. дополнительно его получать не нужно), а получен он м.б. разными путями.
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
Да не, тут дело именно в том, что в 4-ом случае открывается объект без привязки ко вьюхе из которой получен.
Таким образом форму ему можно сменить только сделав replaceItemValue, а это не выход для меня.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
драфт либы по выносу обработки событий LS из скрипта в формах
Общая вводная
Не знаю как остальным мембам нажего комюнити, но мя задолбало лазить по убогому редактору форм и выискивать код ЛС, заботливо там кем-либо оставленный
Идея не нова - написать обработчик On Event и разместить его в библиотеке (я даже видел в тырнетах, но ч-та мну не устроило)

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Моя тестовая имплементация"</div></div><div class="sp-body"><div class="sp-content">
Код:
Option Public
Option Declare
Use "ErrorHandling"
Private Const ERR_BASE=1024
Const UNPROPER_CHAIN=ERR_BASE+1,CS_UNPROPER_CHAIN={Действие не соответствует типу в цепочке}
Const CS_ERR_UIDOC={не установлен объект NotesUIDocument}
Const CS_QUERYOPEN={QUERYOPEN}
Const CS_CALLER_SB={вызывающая ф-ция д.б.:}
Const ACT_TYPES={}	
Private wks As NotesUIWorkspace
Private ses As NotesSession
Private source As NotesUIDocument

Private formObj As FormBase
Private gContinue As Boolean

%REM
Class FormBase
Description: InitObjectsUI нобходимо переопределить
%END REM
Private Class FormBase As ErrorHandler
Private actList List As ActionObject
%REM
Sub New
Description: Comments for Sub
%END REM
Sub New

End Sub
%REM
Function Regiter
Description: Comments for Function
%END REM
Function Register(act As ActionObject) As Boolean
On Error GoTo ErrH
If Not act Is Nothing Then
Dim s As String
s=act.Name
Dim obj As ActionObject
If Not IsElement(actList(s)) Then
Set actList(s)=act
Set obj=act
Else
Set obj=actList(s)
End If
Dim res As ActionObject
Set res=obj.ChainAction(act)
Call obj.Register()
End If
Quit:
Exit Function
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Function
%REM
Sub InitObjectsUI
Description: ф-ция для примера, нужно переписывать для своей реализации
%END REM
Function InitObjectsUI(uidoc As NotesUIDocument, xMode As Integer, xIsnewdoc, Xcontinue)
On Error GoTo ErrH
'устанавливаем глобальную переменную (не д.б. Nothing)
Set source=uidoc
Dim act_QO As TemplQueryOpen, _
act_PO As TemplPostOpen, _
act_QS As TemplQuerySave
Set act_QO=New TemplQueryopen()
Set act_PO=New TemplPostOpen()
Set act_QS=New TemplQuerySave()
Call Me.Register(act_QO)
Call Me.Register(act_PO)
Dim tmp As New TemplQueryRecalc()
Call Me.Register(tmp)
Call Me.Register(act_QS)
Call act_QO.Action(uidoc, xMode, xIsnewdoc, Xcontinue)
Quit:
Exit Function
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Function
End Class

%REM
Class ActionObject
Description: Comments for Class
%END REM
Class ActionObject As ErrorHandler
Private actName As String
Private actObj As Variant
Private actNext As ActionObject
Private isRegistred As Boolean

Sub New(obj, xName As String)
Me.actName=xName
Set Me.actObj=obj
End Sub

Public Property Get Name As String
Me.Name=actName
End Property
%REM
Property Get Object
Description: Comments for Property Get
%END REM
Public Property Get Object As Variant
Set Me.Object=actObj
End Property

%REM
Function ChainAction
Description: определяет цепочку обработки однотипных событий
%END REM
Public Function ChainAction(nxt As ActionObject) As ActionObject
If nxt Is actNext Or nxt Is Me Then Set ChainAction=actNext:Exit Function
If UCase(actName) <> nxt.Name Then Error UNPROPER_CHAIN,CS_UNPROPER_CHAIN
Set actNext=nxt
Set ChainAction=actNext
End Function
%REM
Sub Register
Description: Comments for Sub
%END REM
Sub Register

End Sub
End Class

%REM
Class FromAction
Description: Comments for Class
%END REM
Class FormAction As ActionObject
Sub New(uidoc As NotesUIDocument, xName As String), ActionObject(uidoc, xName)
If uidoc Is Nothing Then Error ERR_BASE, CS_ERR_UIDOC
Set source=uidoc
End Sub
End Class

%REM
Class ActionPostOpen
Description: Comments for Class
%END REM
Private Class TemplPostOpen As FormAction
Sub New(), FormAction(source, {PostOpen})
'		Set source=uidoc
End Sub
Sub Action(uidoc As NotesUIDocument)
Print {Action:} &Me.actName
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event PostOpen From source Call Action
Me.isRegistred=True
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub
End Class

Private Class TemplQueryopen As FormAction
Sub New(), FormAction(source, {Queryopen})
End Sub

Sub Action(uidoc As NotesUIDocument, xMode As Integer, xIsnewdoc, xContinue)
Print {Action:} &Me.actName
'		xcontinue=False
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event QueryOpen From source Call Action
Me.isRegistred=true
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub
End Class
%REM
Class QuerySave
Description: Comments for Class
%END REM
Private Class TemplQuerySave As FormAction
Sub New(), FormAction(source, {QuerySave})
End Sub
Sub Action(uidoc As NotesUIDocument, xContinue)
Print {Action:} &Me.actName
xContinue=False
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event QuerySave From source Call Action
Me.isRegistred=True
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub
End Class

%REM
Class TemplQueryRecalc
Description: Comments for Class
%END REM
Private Class TemplQueryRecalc As FormAction
Sub New(), FormAction(source, {QueryRecalc})
End Sub
Sub Action(uidoc As NotesUIDocument, Continue)
Print {Action:} &Me.actName
Continue=False
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event QueryRecalc From source Call Action
Me.isRegistred=True
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub
End Class

%REM
Class TemplPostSave
Description: Comments for Class
%END REM
Private Class TemplPostSave As FormAction
Sub New(), FormAction(source, {PostSave})
'		Set source=uidoc
End Sub
Sub Action(uidoc As NotesUIDocument)
Print {Action:} &Me.actName
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event PostSave From source Call Action
Me.isRegistred=True
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub

End Class

%REM
Class TemplPostRecalc
Description: Comments for Class
%END REM
Private Class TemplPostRecalc As FormAction
Sub New(), FormAction(source, {PostRecalc})
'		Set source=uidoc
End Sub
Sub Action(uidoc As NotesUIDocument)
Print {Action:} &Me.actName
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event PostRecalc From source Call Action
Me.isRegistred=True
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub

End Class

%REM
Class TemplQueryClose
Description: Comments for Class
%END REM
Private Class TemplQueryClose As FormAction
Sub New(), FormAction(source, {QueryClose})
End Sub
Sub Action(uidoc As NotesUIDocument, xContinue)
Print {Action:} &Me.actName
xContinue=False
End Sub

Sub Register
On Error GoTo ErrH
If Not Me.IsRegistred Then
On Event QueryClose From source Call Action
Me.isRegistred=True
End If
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError
Resume Quit
End Sub
End Class
Sub Initialize
Set wks=New NotesUIWorkspace
Set ses=New NotesSession
Set formObj=New FormBase
gContinue=True
End Sub

%REM
Sub InitObjects
Description: Comments for Sub
%END REM
Sub InitObjects
On Error GoTo ErrH
Dim formObj As New FormBase
Dim act_QO As New TemplQueryopen()
Dim act_PO As New TemplPostOpen()
Call formObj.Register(act_QO)
Call formObj.Register(act_PO)
Quit:
Exit Sub
ErrH:
Error ERR_BASE, RaiseError()
Resume Quit
End Sub

%REM
Sub InitObjectsUI
Description: вызывать нужно из QueryOpen
%END REM
Sub InitObjectsUI(uidoc As NotesUIDocument, xMode As Integer, xIsnewdoc, Xcontinue)
On Error GoTo ErrH
If CStr(GetThreadInfo(LSI_THREAD_CALLPROC))<> CS_QUERYOPEN Then _
Error ERR_BASE, CS_CALLER_SB &CS_QUERYOPEN
If gContinue Then
Call formObj.InitObjectsUI(Uidoc, Xmode, Xisnewdoc, Xcontinue)
Else
xContinue=gcontinue
End if
Quit:
Exit Sub
ErrH:
gContinue=false
Error ERR_BASE, RaiseError()
Resume Quit
End Sub

Добавлено: все шаманство вынесено в Function InitObjectsUI(uidoc As NotesUIDocument, xMode As Integer, xIsnewdoc, Xcontinue)
класса FormBase
предполагается что по образу классов Teml... будут наманьячены свои, в своей либе (потому они и приватные сделаты)
подключение к форме - в событии QueryOpen (минимальный кастыль защиты поставлен, в ф-ции либы InitObjectsUI)

Добавлено: да... цепочку обработки в зареганом списке я не делал (просто поленился :) )
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
ошибка в ChainAction
If nxt Is actNext Or nxt Is Me Then Set ChainAction=actNext:Exit Function
д.б.
If nxt Is actNext Or nxt Is Me Then Set ChainAction=nxt:Exit Function
и ваще - могут быть ошибки - я не гонял код и писал на коленке :)
да и похорошему - там цепочку проверять надо (типа хэш создавать для контроля уникальности объектов), это так - базовая заглушка
 

VladSh

начинающий
Lotus Team
11.12.2009
1 784
157
BIT
57
Что-то такое есть и у нас. На QO производится инициализация объекта, а в методе инициализации утанавливаются события на вызов определённых методов.
Для некоторых контролов (полей) тоже есть.
Такое же на вьюхах, включая обработку InViewEdit и QueryOpenDocument.
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
и ваще - могут быть ошибки - я не гонял код и писал на коленке wink.gif
Ну да, как -то подключение несуществующей библиотеки и ошибка в обработчике ошибок.
Resume Quit еще лишний до него не дойдет)

Я пока не понимаю необходимости такого объекта... может не дорос :)
У меня обработка завязана на событиях PO, QMC, QS и иногда на PS.
Только разве что на PO часто код одинаков, забить карточку начальными данными. (просто вызов одной функции)
А в остальном разница сильно, в такую библу не сунешь...
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
там просто нет либы ErrorHandling
я уже выкладывал её, где-то здесь
смысл либы - писать объекты экшенов на соответ события и регать их в объекте формы
в саму форму - ссылка на либу и вызов инициализации
объекты можно соединять в цепочку (начало написано), проход по цепочке просто не изобразил :)

Добавлено: <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"вот она, ErrorHandling"</div></div><div class="sp-body"><div class="sp-content">
Код:
Option Public
Option Declare
%INCLUDE "lserr.lss"
'Uselsx "*lsxlc"
Uselsx "*javacon"
%INCLUDE "lsconst.lss"
Const ERR_FIELDFORMAT=1100
Const ERR_CHILDSOURCE=1200
Const MSG_FIELDFORMAT="индекс вне диапозона массива форматирования"
Const MSG_CHILSOURCE={элемент списка "0" д.б. равен имени view}
Dim debug As Boolean
Dim log2file As Boolean

Dim logStream As NotesStream
Private ses As NotesSession
Private db As NotesDatabase

Class ErrorHandler

Sub ClrError()
End Sub
Sub New()
Call Me.ClrError()
End Sub
Function GetModuleInfo() As String
Dim thisType As String, modInfo As String	
thisType= Typename(Me)
' Not a class, use the calling module instead
If (thisType = "") Then thisType = Getthreadinfo(11)
modInfo = thisType & "::" & Getthreadinfo(10) & ": "
GetModuleInfo=modInfo
End Function
Function RaiseError() As String
Dim es As String
es=GetModuleInfo()
If (Err = 0) Then
es = es + "Manually raised an error"
Else
es = es + "err. (" + Trim(Str(Err)) + ") " + Error$ + " l. "+ Trim(Str(Erl))
End If
Print es
Me.RaiseError=es & Chr(10)
If (Not logStream Is Nothing) And log2file Then Call logStream.WriteText(es,EOL_PLATFORM)
Call Me.ClrError()
End Function
End Class

Class ErrorHandlerWJ As ErrorHandler
Private jSession As JavaSession	
Private jError As JavaError	
Sub New()
On Error Goto errorhandler
Set jSession= New JAVASESSION
ExitFunction:
Exit Sub
errorhandler:
Call ErrorHandler..RaiseError()
Resume ExitFunction
End Sub
Function RaiseError() As String
Set jError = jSession.getLastJavaError()
Dim es As String
If (jError.errorMsg = "") Then		
es=ErrorHandler..RaiseError()
Else
es=GetModuleInfo()+"Error at line " & Erl & ": " & jError.errorMsg
Print es
jSession.ClearJavaError			
End If
RaiseError=es
If (Not logStream Is Nothing) And log2file Then Call logStream.WriteText(es,EOL_PLATFORM)
End Function
End Class
Sub Initialize
debug=False
Set ses=New NotesSession
Set db=ses.CurrentDatabase
Set logStream=ses.CreateStream
Dim dt As New NotesDateTime({Today})
dt.SetNow
Dim fname As String
fname= {_} &Replace(Replace(Replace(dt.LocalTime,{:},{-}),{ },{_}),{.},{-}) &_
{#} &db.ReplicaID &_
{-} &Replace(Getthreadinfo(LSI_THREAD_CALLMODULE),{*},{}) &_
{.log}

If Not logStream.Open(fname,{UTF-8}) Then
'		logStream=Nothing
End If
'	Msgbox fname &Chr(10) &logStream.WriteText({*-------------start ------------*})
End Sub
Sub Terminate
'	If Not logStream Is Nothing Then logStream.Close
End Sub
Function RaiseErrorMsg()
Dim thisType As String
Dim es As String
'thisType = Typename(Me)
' Not a class, use the calling module instead
If (thisType = "") Then thisType = Getthreadinfo(11)
es = thisType & "::" & Getthreadinfo(10) & ": "
If (Err = 0) Then
es = es + "Manually raised an error"
Else
es = es + "Run time error: (" + Trim(Str(Err)) + ") " + Error$ + " at line: "+ Trim(Str(Erl))
End If
Msgbox es
End Function
Sub DbgMsg(txt As String)
If (debug) Then Print txt
End Sub
Sub Alert(s As String)
Messagebox s, MB_OK+MB_ICONSTOP
End Sub
Function RaiseError() As String
Dim thisType As String
Dim es As String
'thisType = Typename(Me)
' Not a class, use the calling module instead
If (thisType = "") Then thisType = Getthreadinfo(11)
es = thisType & "::" & Getthreadinfo(10) & ": "
If (Err = 0) Then
es = es + "Manually raised an error"
Else
es = es + "err. (" + Trim(Str(Err)) + ") " + Error$ + " l."+ Trim(Str(Erl))
End If
Print es
RaiseError=es + Chr(10)
If (Not logStream Is Nothing) And log2file Then Call logStream.WriteText(es,EOL_PLATFORM)
End Function
Function LogMsg(curLine As Long, msg As String)
If (Not logStream Is Nothing) And log2file Then Call logStream.WriteText({#} &Format(Cstr(curLine), {000000}) &{:} &msg,EOL_PLATFORM)
End Function
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
Да про либу понятно, у меня она своя да и у многих думаю так, так что это просто придирка.
смысл либы - писать объекты экшенов на соответ события и регать их в объекте формы
Получается для каждой системы такая либа будет уникальна...
В результате разработка формы сводится к тому, чтобы заполнить события формы вызовами из либы, да поля расставить.
А все остальное в либе. Хм... имеет конечно смысл.
А что с подформами, у которых свои события?
Скажем... подформа встроена в несколько документов и выполняет общий для них код, но при это у каждой формы еще свои события прописаны. Если использовать данную либу конфликты элементов/объектов будут?
У нас такое "наследство" есть, но переделать не дают.
А скажем система, в которой предусмотрено отображение сразу двух документов и работа с ними?
Как пример: дискуссия при визировании.
Вот интересно, какие могут быть проблемы...
Идея конечно хорошая, в формах не очень удобно работать порой, вот только лично я сильно недоверчив к таким глобальным подходам, но это личное :)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
Получается для каждой системы такая либа будет уникальна...
для каждой формы
и переменная (source) д.б. вне объекта (т.е. я не могу взять мембер класса как from для On Event - так индусы написали)
в каждую форму вкл. либа, а вот инстанцирование объектов (по типу формы) - эту уже на вкус реализатора

Добавлено: на самом деле - именно объекты и дают возможность делать инстанс по контексту, в даном варианте - решение в лоб - одна либа на форму
но никто не мешает использовать более гибкую схему

Добавлено:
чтобы заполнить события формы вызовами из либы
вот этого и не нужно..., заполняется только QO
остальные подключаются автоматически (в либе, а не в форме)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!