Lotus C++ Api

  • Автор темы SparkLone
  • Дата начала
S

SparkLone

Гость
#1
Доброго,
Кто нибудь имеет опыт работы с сабжем?
99 процентов кода уже работает, но при попытке сохранить LNNote выкидывается странное сообщение
"Error: Signature on document is invalid (inconsistent field signatures)" и не сохраняет изменения.
Мне надо по сути изменить Database Script, другого пути кроме как перебор всех LNNote что то не нашел.. Читает, а вот сохранить не получается..
 

Kee_Keekkenen

Well-Known Member
05.09.2006
639
6
#2
кроме замены исходника в $DBScript его еще откомпилировать нужно и положить $DBScript_O, оба эти поля после изменения должны быть подписаны..
 
S

SparkLone

Гость
#3
Для: Kee_Keekkenen
Точно, видел такой LNNote, правда даже подумать не мог что там что то откомпилированное лежит...
Не могли бы вы рассказать поподробней, как программно откомпилить, подписать (кем лучше подписывать), желательно с примером кода? Информации в инете практически ноль по C++ Api для лотуса.. (
 

Kee_Keekkenen

Well-Known Member
05.09.2006
639
6
#4
для компиляции скриптов есть пара функций NSFNoteLSCompile и NSFNoteLSCompileExt это C Api функции, а ты как я понимаю на на С++ пишешь.. как это писать я не знаю.. в LS в классе NotesItem есть метод Sign (NSFNoteSignExt, NSFNoteSignExt3 в C Api)..
 
S

SparkLone

Гость
#5
Для: Kee_Keekkenen
Да.. Что то я таких классов в C++ API не нашел (
Охх.. Не было печали, как бы не пришлось все под C API переписывать и не дай бог если в нем нет того что есть в C++ API и нужно будет в проекте..
Спасибо за наводку, буду ковырять.
 
S

SparkLone

Гость
#7
Для: Kee_Keekkenen
Эхх.. Чем бы программист не занимался, лишь бы за***лся.. Действительно есть такая функция NSFNoteLSCompile. По документации есть только в C API, поматерившись, остыв, решил проверить навскидку. Оказалось что хотя в хелпе нигде не указано, но из под C++ API тоже можно ее вызывать.
Код:
	note.GetItems(&items);
for (j = 0; j < items.GetCount(); j++)
{
item = items[j];
if(item.GetName()== "$DBScript")
{
text = item;
LNString lns(GetFileContent("dbscript.txt").c_str());
text.SetValue(lns);
try
{
note.Sign();												note.Save();
nHandle = note.GetNoteHandle();
STATUS stat = NSFNoteLSCompile(db.GetDatabaseHandle(), nHandle, 0);
if (stat=NSFNoteUpdate(nHandle,0))
{
printf("Error: can't update note after LS Compilen");
}
break;
}
catch (LNSTATUS	lnerror)
{
ShowError(lnerror);
}
}
}
note.Close();
Все отрабатывает даже без ошибок.. Но, после этого пытаюсь открыть базу - ловлю ошибку
---------------------------
Lotus Notes
---------------------------
Generic LSE Failure (no more info!)
---------------------------
OK
---------------------------

Слов нет, одни эмоции (
 
S

SparkLone

Гость
#9
Не..
Если вызывать
Код:
STATUS stat = NSFNoteLSCompile(db.GetDatabaseHandle(), nHandle, 0);
note.Sign();
При sign'е вылетает "Error: Object has not been initialized"
 

Kee_Keekkenen

Well-Known Member
05.09.2006
639
6
#10
по моему вот такой порядок функций должен быть..

WinNSFNoteOpenByUNID(m_objDbDesign.dbhandle, aUnid,0 , hNote)
WinNSFNoteLSCompile(m_objDbDesign.dbhandle,hNote,0)
WinNSFNoteSign(hNote)
WinNSFNoteUpdate(hNote,0)
WinNSFNoteClose(hNote)
 
S

SparkLone

Гость
#11
Для: Kee_Keekkenen
По моему та же фигня выходит.. не могу уверять наверняка, т.к. использую все таки C++ API, посему немного переделал, вместо твоего вариант сделал что то вроде:
Код:
	NOTEHANDLE hNote;
HANDLE dbHandle;
dbHandle = db.GetDatabaseHandle(TRUE);
LNNote note = GetDBScriptNode(db); //моя функция
hNote = note.GetNoteHandle(TRUE);
... код изменяющий скрипты.. 
NSFNoteLSCompile(dbHandle,hNote,0);
NSFNoteSign(hNote);
NSFNoteUpdate(hNote,0);
note.close();
db.close();
В процессе выполнения - ни одного warning'а, все отрабатывает чисто и результат все тот же: "Generic LSE Failure (no more info!)". Останавливаю сервер, через дизайнер смотрю базу - все скрипты слетели (хотя програмным кодом до сих пор видяться нормально).

Может конечно дело в том как меняются сорцы скриптов, но иначе прийдется переходить и дальше на C API.. Надо будет попробовать менять скрипты через C API, если не выйдет - накатать прототип полностью на C API..
 

Kee_Keekkenen

Well-Known Member
05.09.2006
639
6
#12
1. а если руками в дизайнере этот код вставить и откомпилировать ?
2. а если на api только заменить текст кода скрипта и сохранить, а после в дизайнере посмотреть корректность вставки кода и пересохранить (компилировать) ?
3. если все ок по первым пунктам, то остается еще возможность того, что библиотека действительно корректно заменена и откомпилирована, но ссылки на нее из других объектов базы нарушены, поэтому имеет смысл в конце всего на api перекомпилировать все скрипты базы, как это обычно делается в дизайнере...

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

SparkLone

Гость
#13
Kee_Keekkenen
1. Не совсем понимаю как это можно сделать. Посредством API ведь можно снять/задать лишь дамп "Database Script".
Типа:
Код:
'++LotusScript Development Environment:2:5:(Options):0:74
Option Public
Option Declare
Option Compare Nocase
Use "Common"

'++LotusScript Development Environment:2:5:(Forward):0:1
Declare Class UIMemoDocument
Declare Function QuerySaveExtension(Source As notesUIdocument, lngActionInProgress As Long, continue As Variant) As Integer
Declare Function PostSaveExtension(Source As notesUIdocument, lngActionInProgress As Long) As Integer
Declare Function QueryCloseExtension(Source As notesUIdocument, continue As Integer) As Integer
Declare Function PostOpenExtension(Source As notesUIdocument, lngFlags As Long) As Integer
Declare Sub FaxToProc(Source As Notesuidocument, Continue As Variant)
Declare Function FaxGetDomain () As String
Declare Function FaxLookupNAB (CurrentName As Variant, SendToList() As Variant, GroupList() As Variant, FaxDomain As Variant) As Integer
Declare Function FaxMsgText (MsgNumber As Variant, TextInsert As String) As String
И т.д.. "Database script" как я понимаю не считается скриптом, ,чтобы работать с ним посредством удобного API, оттуда и проблемы ( db.ScriptLibraryExists("$DBScript") говорит false)
Таким образом я добираюсь через список всех LNNote.
Для нахождения LNNote с 'Database Script', написал функцию
Код:
LNNote XanderGetDBScriptNode(LNDatabase& db)
{
LNNOTETYPE type;
LNNoteArray notes;
LNNote note;
LNItem item;
BOOL is_agent = true;
LNDocument doc;
LNINT i, count;
LNText text;
LNString script_text;

db.GetNotes(&notes);
count = notes.GetCount();
for (i = 0; i < count; i++)
{
note = notes[i];
type = note.GetNoteType();
if (LNNOTETYPE_DATABASE_SCRIPT == note.GetNoteType())
{
note.Open();
// open form or subform note
if (note.HasItem(DESIGN_FLAGS))
{
LNText flags_item; // get $Flags item
note.GetItem(DESIGN_FLAGS, &flags_item);
LNINT counter = flags_item.GetCount();
for (LNINT j = 0; j < counter; j++)
{
LNINT loc; // needed by FindChar, but not used here
if (LNString(flags_item[j]).FindChar(DESIGN_FLAG_DATABASESCRIPT, 0, &loc) == LNNOERROR)
{
return note;
}
}
}
}
}
}
А потом использую найденный нод так:
Код:
	LNItemArray items;
note.GetItems(&items);
cout << items.GetCount() << endl;
for (j = 0; j < items.GetCount(); j++)
{
item = items[j];
if(item.GetName()== "$DBScript")
{
text = item;
LNString lns(GetFileContent("dbscript.txt").c_str());
text.SetValue(lns);
.. дальше уже подписываем, компилим, сохраняем
}
}
note.Close(); // don't need this open anymore
2. А если сделать sign и save (без sign'а не сохранить), и без рекомпиляции октрыть базу в дизайнере - при просмотре Database script - Он вообще покажет что там пусто.. Хотя программно по прежнему прочитать можно будет.
 

Kee_Keekkenen

Well-Known Member
05.09.2006
639
6
#14
просто в первом пункте я имел ввиду, что правильно ли (?) заносится текст библиотеки в поле.. ведь Database script это документ, и соответственно, можно только заменить значение поля $DBScript и сохранить его.. вероятно, если удастся сохранить, то при открытии бд может возникнуть какая-нибудь ошибка, хотя и не должно, потому что использоваться должны ранее скомпилированные скрипты в $ScriptLib_O.. этим я хотел понять правильно ли заносится текст кода библиотеки с тем, что открыть базу в дизайнере и посмотреть можно ли пересохранить библиотеку и будут ли ошибки..

но это все же уход в сторону, только тестирование..

а как на счет перекомпиляции всех скриптов базы, после удачной замены и компиляции библиотеки ?
 

Omh

Well-Known Member
Lotus team
04.07.2007
2 210
1
#15
Камрады, а почему не хотите прогнать DatabaseScript через очередь
DXLExporter -> DOMPraser -> DXLImporter?

В DOMParser'e поменять скрипт на нужный, а DXLImporter сам скомпилит при импорте.
Если же дизайн закрыт (тогда не сработает DXLExporter), то можно вообще на лету сгенерить нужный DatabaseScript и его импортнуть.
Структура XML там совсем несложная.
 
S

SparkLone

Гость
#16
Kee_Keekkenen
К сожалению не ясно что именно делается не правильно. Текущий текст $DBScript получаю так:
Код:
	LNItem item; //здесь DBScript, как именно он получается писал выше
LNText text;
LNString script_text; //сюда дампится содержание DBScript в текстовом виде

text = item;
text.GetText(&script_text);
И если его сразу же записать обратно как было показано выше - проблемы остаются. То ли не тот текст скрипта (не в том формате) подставляется, то ли технология сохранения/компиляции не та..

А на счет рекомпиляции.. Я попытался отрекомпилировать все LNNote а не только скрипты (по той причине что тот же DBScript почему то не считается скриптом). Под самый конец (уже откомпилировалось порядка 450 из 560 элементов) - вылетели ошибки и все упало. И вообще переподписывать всю базу на мой взгляд - не самый лучший вариант.. Получается что владельцем всех элементов будет Админ, как то это не есть гуд.. В идеале изменения вообще бы подписать дизайнером баз, не знаю возможно ли это..

Omh
Хм, спасибо за идею, интересный вариант, буду пробовать )
 

Omh

Well-Known Member
Lotus team
04.07.2007
2 210
1
#17
API это конечно как бы круче :rolleyes:
Но тут DXL-кой вполне можно обойтись и даже особо напрягаться не придёться :)
 
S

SparkLone

Гость
#18
Omh
Прототип начинал делать не я, потом разработка на некоторое время была приостановлена, а я уже исходил из сделанного. Многие вещи конечно пришлось делать по другому, но как то в данной ситуации посмотреть в сторону Lotus Script'а не догадался )

P.S. Сдампить всю базу уже удалось, DatabaseScript там присутствует, теперь осталось научиться находить Database Script, чтобы подсовывать его SetInput (а не всю базу), и попробовать записать модификации, заработает или нет.
 
S

SparkLone

Гость
#19
Omh
А у Вас совершенно случайно нет опыта с этой техникой? )
С XSLT поработать в свое время довелось, но как это все реализовано в Lotus'е что то не ясно.. Взял пример из help'а

Код:
Sub Click(Source As Button)
Dim session As New NotesSession
filename$ = "dump"

Dim xmlin As NotesStream
Set xmlin=session.CreateStream
If Not xmlin.Open("d:\dbscripts\" & filename$ & ".dxl") Then
Messagebox "DXL Cannot open " & filename$,, "Error"
Exit Sub
End If
If xmlin.Bytes = 0 Then
Messagebox "DXL File did not exist or was empty",, filename$
Exit Sub
End If

Dim xslin As NotesStream
Set xslin=session.CreateStream
If Not xslin.Open("d:\dbscripts\" & filename$ & ".xsl") Then
Messagebox "XSL Cannot open " & filename$,, "Error"
Exit Sub
End If
If xslin.Bytes = 0 Then
Messagebox "XSL File did not exist or was empty",, filename$
Exit Sub
End If

Dim xmlout As NotesStream
Set xmlout=session.CreateStream
Call xmlout.Open("d:\dbscripts\" & filename$ & ".txt")
Call xmlout.Truncate

Dim transformer As NotesXSLTransformer
Set transformer=session.CreateXSLTransformer(xmlin, xslin, _
xmlout)
Call transformer.Process
End Sub
В качестве xsl подставлял (то что в примере тоже не прокатило) это, ожидая что Лотус просто сделает копию, пееркопировав все ноды (так по крайней мере работал движок с которым я работал раньше)
Код:
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" > 
<!-- By default, copy everything -->
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Но на выходе я получаю глупость, а именно копию XSL файла, только со слегка поехавшим форматированием..

Задумка то моя думаю ясна - по дефолту все перекопировать, кроме нужных мне нод, которые я заменю.. Но по использованию XSL в Лотусе практически нет инфы..
 

Omh

Well-Known Member
Lotus team
04.07.2007
2 210
1
#20
Не, XSLTransformer тебе не нужОн.
Я предлагал путь DXLExp -> DOMParser -> DXLImp.
Тут есть статья, где чел описывал настройку embedded view на любую базу через DXL.
Это примерно то, что тебе нужно.

Ещё можешь глянуть вот это.